]> git.saurik.com Git - apple/xnu.git/blob - libkern/c++/OSKext.cpp
d79b4b64e002f6be1dcf4ee4e257d44cd448bfa2
[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
117 /* Prelinked arm kexts do not have VM entries because the method we use to
118 * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does
119 * not work on ARM. To get around that, we must free prelinked kext
120 * executables with ml_static_mfree() instead of kext_free().
121 */
122 #if __i386__ || __x86_64__
123 #define VM_MAPPED_KEXTS 1
124 #define KASLR_KEXT_DEBUG 0
125 #define KASLR_IOREG_DEBUG 0
126 #elif __arm__ || __arm64__
127 #define VM_MAPPED_KEXTS 0
128 #define KASLR_KEXT_DEBUG 0
129 #else
130 #error Unsupported architecture
131 #endif
132
133 #if PRAGMA_MARK
134 #pragma mark Constants & Macros
135 #endif
136 /*********************************************************************
137 * Constants & Macros
138 *********************************************************************/
139
140 /* Use this number to create containers.
141 */
142 #define kOSKextTypicalLoadCount (150)
143
144 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict.
145 * A loaded kext will no dependents or external retains will have 2 retains.
146 */
147 #define kOSKextMinRetainCount (1)
148 #define kOSKextMinLoadedRetainCount (2)
149
150 /**********
151 * Strings and substrings used in dependency resolution.
152 */
153 #define APPLE_KEXT_PREFIX "com.apple."
154 #define KERNEL_LIB "com.apple.kernel"
155
156 #define PRIVATE_KPI "com.apple.kpi.private"
157
158 /* Version for compatbility pseudokexts (com.apple.kernel.*),
159 * compatible back to v6.0.
160 */
161 #define KERNEL6_LIB "com.apple.kernel.6.0"
162 #define KERNEL6_VERSION "7.9.9"
163
164 #define KERNEL_LIB_PREFIX "com.apple.kernel."
165 #define KPI_LIB_PREFIX "com.apple.kpi."
166
167 #define STRING_HAS_PREFIX(s, p) (strncmp((s), (p), strlen(p)) == 0)
168
169 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes
170 #define MINIMUM_WAKEUP_SECONDS (30)
171
172 /*********************************************************************
173 * infoDict keys for internally-stored data. Saves on ivar slots for
174 * objects we don't keep around past boot time or during active load.
175 *********************************************************************/
176
177 /* A usable, uncompressed file is stored under this key.
178 */
179 #define _kOSKextExecutableKey "_OSKextExecutable"
180
181 /* An indirect reference to the executable file from an mkext
182 * is stored under this key.
183 */
184 #define _kOSKextMkextExecutableReferenceKey "_OSKextMkextExecutableReference"
185
186 /* If the file is contained in a larger buffer laid down by the booter or
187 * sent from user space, the OSKext stores that OSData under this key so that
188 * references are properly tracked. This is always an mkext, right now.
189 */
190 #define _kOSKextExecutableExternalDataKey "_OSKextExecutableExternalData"
191
192 #define OS_LOG_HDR_VERSION 1
193 #define NUM_OS_LOG_SECTIONS 2
194
195 #define OS_LOG_SECT_IDX 0
196 #define CSTRING_SECT_IDX 1
197
198 #if PRAGMA_MARK
199 #pragma mark Typedefs
200 #endif
201 /*********************************************************************
202 * Typedefs
203 *********************************************************************/
204
205 /*********************************************************************
206 * osLogDataHeaderRef describes the header information of an OSData
207 * object that is returned when querying for kOSBundleLogStringsKey.
208 * We currently return information regarding 2 sections - os_log and
209 * cstring. In the case that the os_log section doesn't exist, we just
210 * return an offset and length of 0 for that section.
211 *********************************************************************/
212 typedef struct osLogDataHeader {
213 uint32_t version;
214 uint32_t sect_count;
215 struct {
216 uint32_t sect_offset;
217 uint32_t sect_size;
218 } sections[0];
219 } osLogDataHeaderRef;
220
221 /*********************************************************************
222 * MkextEntryRef describes the contents of an OSData object
223 * referencing a file entry from an mkext so that we can uncompress
224 * (if necessary) and extract it on demand.
225 *
226 * It contains the mkextVersion in case we ever wind up supporting
227 * multiple mkext formats. Mkext format 1 is officially retired as of
228 * Snow Leopard.
229 *********************************************************************/
230 typedef struct MkextEntryRef {
231 mkext_basic_header * mkext; // beginning of whole mkext file
232 void * fileinfo;// mkext2_file_entry or equiv; see mkext.h
233 } MkextEntryRef;
234
235 #if PRAGMA_MARK
236 #pragma mark Global and static Module Variables
237 #endif
238 /*********************************************************************
239 * Global & static variables, used to keep track of kexts.
240 *********************************************************************/
241
242 static bool sPrelinkBoot = false;
243 static bool sSafeBoot = false;
244 static bool sKeepSymbols = false;
245
246 /*********************************************************************
247 * sKextLock is the principal lock for OSKext, and guards all static
248 * and global variables not owned by other locks (declared further
249 * below). It must be taken by any entry-point method or function,
250 * including internal functions called on scheduled threads.
251 *
252 * sKextLock and sKextInnerLock are recursive due to multiple functions
253 * that are called both externally and internally. The other locks are
254 * nonrecursive.
255 *
256 * Which locks are taken depends on what they protect, but if more than
257 * one must be taken, they must always be locked in this order
258 * (and unlocked in reverse order) to prevent deadlocks:
259 *
260 * 1. sKextLock
261 * 2. sKextInnerLock
262 * 3. sKextSummariesLock
263 * 4. sKextLoggingLock
264 */
265 static IORecursiveLock * sKextLock = NULL;
266
267 static OSDictionary * sKextsByID = NULL;
268 static OSDictionary * sExcludeListByID = NULL;
269 static OSKextVersion sExcludeListVersion = 0;
270 static OSArray * sLoadedKexts = NULL;
271 static OSArray * sUnloadedPrelinkedKexts = NULL;
272
273 // Requests to kextd waiting to be picked up.
274 static OSArray * sKernelRequests = NULL;
275 // Identifier of kext load requests in sKernelRequests
276 static OSSet * sPostedKextLoadIdentifiers = NULL;
277 static OSArray * sRequestCallbackRecords = NULL;
278
279 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel
280 static OSSet * sAllKextLoadIdentifiers = NULL;
281 static KXLDContext * sKxldContext = NULL;
282 static uint32_t sNextLoadTag = 0;
283 static uint32_t sNextRequestTag = 0;
284
285 static bool sUserLoadsActive = false;
286 static bool sKextdActive = false;
287 static bool sDeferredLoadSucceeded = false;
288 static bool sConsiderUnloadsExecuted = false;
289
290 #if NO_KEXTD
291 static bool sKernelRequestsEnabled = false;
292 #else
293 static bool sKernelRequestsEnabled = true;
294 #endif
295 static bool sLoadEnabled = true;
296 static bool sUnloadEnabled = true;
297
298 /*********************************************************************
299 * Stuff for the OSKext representing the kernel itself.
300 **********/
301 static OSKext * sKernelKext = NULL;
302
303 /* Set up a fake kmod_info struct for the kernel.
304 * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
305 * before OSKext is initialized; that call only needs the name
306 * and address to be set correctly.
307 *
308 * We don't do much else with the kerne's kmod_info; we never
309 * put it into the kmod list, never adjust the reference count,
310 * and never have kernel components reference it.
311 * For that matter, we don't do much with kmod_info structs
312 * at all anymore! We just keep them filled in for gdb and
313 * binary compability.
314 */
315 kmod_info_t g_kernel_kmod_info = {
316 /* next */ 0,
317 /* info_version */ KMOD_INFO_VERSION,
318 /* id */ 0, // loadTag: kernel is always 0
319 /* name */ kOSKextKernelIdentifier, // bundle identifier
320 /* version */ "0", // filled in in OSKext::initialize()
321 /* reference_count */ -1, // never adjusted; kernel never unloads
322 /* reference_list */ NULL,
323 /* address */ 0,
324 /* size */ 0, // filled in in OSKext::initialize()
325 /* hdr_size */ 0,
326 /* start */ 0,
327 /* stop */ 0
328 };
329
330 /* Set up a fake kmod_info struct for statically linked kexts that don't have one. */
331
332 kmod_info_t invalid_kmod_info = {
333 /* next */ 0,
334 /* info_version */ KMOD_INFO_VERSION,
335 /* id */ UINT32_MAX,
336 /* name */ "invalid",
337 /* version */ "0",
338 /* reference_count */ -1,
339 /* reference_list */ NULL,
340 /* address */ 0,
341 /* size */ 0,
342 /* hdr_size */ 0,
343 /* start */ 0,
344 /* stop */ 0
345 };
346
347 extern "C" {
348 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c,
349 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s,
350 // misc_protos.h, db_low_trace.c, kgmacros
351 // 'kmod' is a holdover from the old kmod system, we can't rename it.
352 kmod_info_t * kmod = NULL;
353
354 #define KEXT_PANICLIST_SIZE (2 * PAGE_SIZE)
355
356
357 static char * loaded_kext_paniclist = NULL;
358 static uint32_t loaded_kext_paniclist_size = 0;
359
360 AbsoluteTime last_loaded_timestamp;
361 static char last_loaded_str_buf[2 * KMOD_MAX_NAME];
362 static u_long last_loaded_strlen = 0;
363 static void * last_loaded_address = NULL;
364 static u_long last_loaded_size = 0;
365
366 AbsoluteTime last_unloaded_timestamp;
367 static char last_unloaded_str_buf[2 * KMOD_MAX_NAME];
368 static u_long last_unloaded_strlen = 0;
369 static void * last_unloaded_address = NULL;
370 static u_long last_unloaded_size = 0;
371
372 // Statically linked kmods described by several mach-o sections:
373 //
374 // kPrelinkInfoSegment:kBuiltinInfoSection
375 // Array of pointers to kmod_info_t structs.
376 //
377 // kPrelinkInfoSegment:kBuiltinInfoSection
378 // Array of pointers to an embedded mach-o header.
379 //
380 // __DATA:kBuiltinInitSection, kBuiltinTermSection
381 // Structors for all kmods. Has to be filtered by proc address.
382 //
383
384 static uint32_t gBuiltinKmodsCount;
385 static kernel_section_t * gBuiltinKmodsSectionInfo;
386 static kernel_section_t * gBuiltinKmodsSectionStart;
387
388 static const OSSymbol * gIOSurfaceIdentifier;
389 vm_tag_t gIOSurfaceTag;
390
391 /*********************************************************************
392 * sKextInnerLock protects against cross-calls with IOService and
393 * IOCatalogue, and owns the variables declared immediately below.
394 *
395 * Note that sConsiderUnloadsExecuted above belongs to sKextLock!
396 *
397 * When both sKextLock and sKextInnerLock need to be taken,
398 * always lock sKextLock first and unlock it second. Never take both
399 * locks in an entry point to OSKext; if you need to do so, you must
400 * spawn an independent thread to avoid potential deadlocks for threads
401 * calling into OSKext.
402 **********/
403 static IORecursiveLock * sKextInnerLock = NULL;
404
405 static bool sAutounloadEnabled = true;
406 static bool sConsiderUnloadsCalled = false;
407 static bool sConsiderUnloadsPending = false;
408
409 static unsigned int sConsiderUnloadDelay = 60; // seconds
410 static thread_call_t sUnloadCallout = 0;
411 static thread_call_t sDestroyLinkContextThread = 0; // one-shot, one-at-a-time thread
412 static bool sSystemSleep = false; // true when system going to sleep
413 static AbsoluteTime sLastWakeTime; // last time we woke up
414
415 /*********************************************************************
416 * Backtraces can be printed at various times so we need a tight lock
417 * on data used for that. sKextSummariesLock protects the variables
418 * declared immediately below.
419 *
420 * gLoadedKextSummaries is accessed by other modules, but only during
421 * a panic so the lock isn't needed then.
422 *
423 * gLoadedKextSummaries has the "used" attribute in order to ensure
424 * that it remains visible even when we are performing extremely
425 * aggressive optimizations, as it is needed to allow the debugger
426 * to automatically parse the list of loaded kexts.
427 **********/
428 static IOLock * sKextSummariesLock = NULL;
429 extern "C" lck_spin_t vm_allocation_sites_lock;
430 static IOSimpleLock * sKextAccountsLock = &vm_allocation_sites_lock;
431
432 void (*sLoadedKextSummariesUpdated)(void) = OSKextLoadedKextSummariesUpdated;
433 OSKextLoadedKextSummaryHeader * gLoadedKextSummaries __attribute__((used)) = NULL;
434 uint64_t gLoadedKextSummariesTimestamp __attribute__((used)) = 0;
435 static size_t sLoadedKextSummariesAllocSize = 0;
436
437 static OSKextActiveAccount * sKextAccounts;
438 static uint32_t sKextAccountsCount;
439 };
440
441 /*********************************************************************
442 * sKextLoggingLock protects the logging variables declared immediately below.
443 **********/
444 static IOLock * sKextLoggingLock = NULL;
445
446 static const OSKextLogSpec kDefaultKernelLogFilter = kOSKextLogBasicLevel |
447 kOSKextLogVerboseFlagsMask;
448 static OSKextLogSpec sKernelLogFilter = kDefaultKernelLogFilter;
449 static bool sBootArgLogFilterFound = false;
450 SYSCTL_UINT(_debug, OID_AUTO, kextlog, CTLFLAG_RW | CTLFLAG_LOCKED, &sKernelLogFilter,
451 0, "kernel kext logging");
452
453 static OSKextLogSpec sUserSpaceKextLogFilter = kOSKextLogSilentFilter;
454 static OSArray * sUserSpaceLogSpecArray = NULL;
455 static OSArray * sUserSpaceLogMessageArray = NULL;
456
457 /*********
458 * End scope for sKextInnerLock-protected variables.
459 *********************************************************************/
460
461
462 /*********************************************************************
463 * helper function used for collecting PGO data upon unload of a kext
464 */
465
466 static int OSKextGrabPgoDataLocked(OSKext *kext,
467 bool metadata,
468 uuid_t instance_uuid,
469 uint64_t *pSize,
470 char *pBuffer,
471 uint64_t bufferSize);
472
473 /**********************************************************************/
474
475
476
477 #if PRAGMA_MARK
478 #pragma mark OSData callbacks (need to move to OSData)
479 #endif
480 /*********************************************************************
481 * C functions used for callbacks.
482 *********************************************************************/
483 extern "C" {
484 void
485 osdata_kmem_free(void * ptr, unsigned int length)
486 {
487 kmem_free(kernel_map, (vm_address_t)ptr, length);
488 return;
489 }
490
491 void
492 osdata_phys_free(void * ptr, unsigned int length)
493 {
494 ml_static_mfree((vm_offset_t)ptr, length);
495 return;
496 }
497
498 void
499 osdata_vm_deallocate(void * ptr, unsigned int length)
500 {
501 (void)vm_deallocate(kernel_map, (vm_offset_t)ptr, length);
502 return;
503 }
504
505 void
506 osdata_kext_free(void * ptr, unsigned int length)
507 {
508 (void)kext_free((vm_offset_t)ptr, length);
509 }
510 };
511
512 #if PRAGMA_MARK
513 #pragma mark KXLD Allocation Callback
514 #endif
515 /*********************************************************************
516 * KXLD Allocation Callback
517 *********************************************************************/
518 kxld_addr_t
519 kern_allocate(
520 u_long size,
521 KXLDAllocateFlags * flags,
522 void * user_data)
523 {
524 vm_address_t result = 0; // returned
525 kern_return_t mach_result = KERN_FAILURE;
526 bool success = false;
527 OSKext * theKext = (OSKext *)user_data;
528 u_long roundSize = round_page(size);
529 OSData * linkBuffer = NULL;// must release
530
531 mach_result = kext_alloc(&result, roundSize, /* fixed */ FALSE);
532 if (mach_result != KERN_SUCCESS) {
533 OSKextLog(theKext,
534 kOSKextLogErrorLevel |
535 kOSKextLogGeneralFlag,
536 "Can't allocate kernel memory to link %s.",
537 theKext->getIdentifierCString());
538 goto finish;
539 }
540
541 /* Create an OSData wrapper for the allocated buffer.
542 */
543 linkBuffer = OSData::withBytesNoCopy((void *)result, roundSize);
544 if (!linkBuffer) {
545 OSKextLog(theKext,
546 kOSKextLogErrorLevel |
547 kOSKextLogGeneralFlag,
548 "Can't allocate linked executable wrapper for %s.",
549 theKext->getIdentifierCString());
550 goto finish;
551 }
552 linkBuffer->setDeallocFunction(osdata_kext_free);
553 OSKextLog(theKext,
554 kOSKextLogProgressLevel |
555 kOSKextLogLoadFlag | kOSKextLogLinkFlag,
556 "Allocated link buffer for kext %s at %p (%lu bytes).",
557 theKext->getIdentifierCString(),
558 (void *)result, (unsigned long)roundSize);
559
560 theKext->setLinkedExecutable(linkBuffer);
561
562 *flags = kKxldAllocateWritable;
563 success = true;
564
565 finish:
566 if (!success && result) {
567 kext_free(result, roundSize);
568 result = 0;
569 }
570
571 OSSafeReleaseNULL(linkBuffer);
572
573 return (kxld_addr_t)result;
574 }
575
576 /*********************************************************************
577 *********************************************************************/
578 void
579 kxld_log_callback(
580 KXLDLogSubsystem subsystem,
581 KXLDLogLevel level,
582 const char * format,
583 va_list argList,
584 void * user_data)
585 {
586 OSKext *theKext = (OSKext *) user_data;
587 OSKextLogSpec logSpec = 0;
588
589 switch (subsystem) {
590 case kKxldLogLinking:
591 logSpec |= kOSKextLogLinkFlag;
592 break;
593 case kKxldLogPatching:
594 logSpec |= kOSKextLogPatchFlag;
595 break;
596 }
597
598 switch (level) {
599 case kKxldLogExplicit:
600 logSpec |= kOSKextLogExplicitLevel;
601 break;
602 case kKxldLogErr:
603 logSpec |= kOSKextLogErrorLevel;
604 break;
605 case kKxldLogWarn:
606 logSpec |= kOSKextLogWarningLevel;
607 break;
608 case kKxldLogBasic:
609 logSpec |= kOSKextLogProgressLevel;
610 break;
611 case kKxldLogDetail:
612 logSpec |= kOSKextLogDetailLevel;
613 break;
614 case kKxldLogDebug:
615 logSpec |= kOSKextLogDebugLevel;
616 break;
617 }
618
619 OSKextVLog(theKext, logSpec, format, argList);
620 }
621
622 #if PRAGMA_MARK
623 #pragma mark IOStatistics defines
624 #endif
625
626 #if IOKITSTATS
627
628 #define notifyKextLoadObservers(kext, kmod_info) \
629 do { \
630 IOStatistics::onKextLoad(kext, kmod_info); \
631 } while (0)
632
633 #define notifyKextUnloadObservers(kext) \
634 do { \
635 IOStatistics::onKextUnload(kext); \
636 } while (0)
637
638 #define notifyAddClassObservers(kext, addedClass, flags) \
639 do { \
640 IOStatistics::onClassAdded(kext, addedClass); \
641 } while (0)
642
643 #define notifyRemoveClassObservers(kext, removedClass, flags) \
644 do { \
645 IOStatistics::onClassRemoved(kext, removedClass); \
646 } while (0)
647
648 #else
649
650 #define notifyKextLoadObservers(kext, kmod_info)
651 #define notifyKextUnloadObservers(kext)
652 #define notifyAddClassObservers(kext, addedClass, flags)
653 #define notifyRemoveClassObservers(kext, removedClass, flags)
654
655 #endif /* IOKITSTATS */
656
657 #if PRAGMA_MARK
658 #pragma mark Module Config (Startup & Shutdown)
659 #endif
660 /*********************************************************************
661 * Module Config (Class Definition & Class Methods)
662 *********************************************************************/
663 #define super OSObject
664 OSDefineMetaClassAndStructors(OSKext, OSObject)
665
666 /*********************************************************************
667 *********************************************************************/
668 /* static */
669 void
670 OSKext::initialize(void)
671 {
672 OSData * kernelExecutable = NULL;// do not release
673 u_char * kernelStart = NULL;// do not free
674 size_t kernelLength = 0;
675 OSString * scratchString = NULL;// must release
676 IORegistryEntry * registryRoot = NULL;// do not release
677 OSNumber * kernelCPUType = NULL;// must release
678 OSNumber * kernelCPUSubtype = NULL;// must release
679 OSKextLogSpec bootLogFilter = kOSKextLogSilentFilter;
680 bool setResult = false;
681 uint64_t * timestamp = 0;
682 char bootArgBuffer[16];// for PE_parse_boot_argn w/strings
683
684 /* This must be the first thing allocated. Everything else grabs this lock.
685 */
686 sKextLock = IORecursiveLockAlloc();
687 sKextInnerLock = IORecursiveLockAlloc();
688 sKextSummariesLock = IOLockAlloc();
689 sKextLoggingLock = IOLockAlloc();
690 assert(sKextLock);
691 assert(sKextInnerLock);
692 assert(sKextSummariesLock);
693 assert(sKextLoggingLock);
694
695 sKextsByID = OSDictionary::withCapacity(kOSKextTypicalLoadCount);
696 sLoadedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
697 sUnloadedPrelinkedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount / 10);
698 sKernelRequests = OSArray::withCapacity(0);
699 sPostedKextLoadIdentifiers = OSSet::withCapacity(0);
700 sAllKextLoadIdentifiers = OSSet::withCapacity(kOSKextTypicalLoadCount);
701 sRequestCallbackRecords = OSArray::withCapacity(0);
702 assert(sKextsByID && sLoadedKexts && sKernelRequests &&
703 sPostedKextLoadIdentifiers && sAllKextLoadIdentifiers &&
704 sRequestCallbackRecords && sUnloadedPrelinkedKexts);
705
706 /* Read the log flag boot-args and set the log flags.
707 */
708 if (PE_parse_boot_argn("kextlog", &bootLogFilter, sizeof(bootLogFilter))) {
709 sBootArgLogFilterFound = true;
710 sKernelLogFilter = bootLogFilter;
711 // log this if any flags are set
712 OSKextLog(/* kext */ NULL,
713 kOSKextLogBasicLevel |
714 kOSKextLogFlagsMask,
715 "Kernel kext log filter 0x%x per kextlog boot arg.",
716 (unsigned)sKernelLogFilter);
717 }
718
719 sSafeBoot = PE_parse_boot_argn("-x", bootArgBuffer,
720 sizeof(bootArgBuffer)) ? true : false;
721
722 if (sSafeBoot) {
723 OSKextLog(/* kext */ NULL,
724 kOSKextLogWarningLevel |
725 kOSKextLogGeneralFlag,
726 "SAFE BOOT DETECTED - "
727 "only valid OSBundleRequired kexts will be loaded.");
728 }
729
730 PE_parse_boot_argn("keepsyms", &sKeepSymbols, sizeof(sKeepSymbols));
731 #if CONFIG_DTRACE
732 if (dtrace_keep_kernel_symbols()) {
733 sKeepSymbols = true;
734 }
735 #endif /* CONFIG_DTRACE */
736 #if KASAN_DYNAMIC_BLACKLIST
737 /* needed for function lookup */
738 sKeepSymbols = true;
739 #endif
740
741 /* Set up an OSKext instance to represent the kernel itself.
742 */
743 sKernelKext = new OSKext;
744 assert(sKernelKext);
745
746 kernelStart = (u_char *)&_mh_execute_header;
747 kernelLength = getlastaddr() - (vm_offset_t)kernelStart;
748 kernelExecutable = OSData::withBytesNoCopy(
749 kernelStart, kernelLength);
750 assert(kernelExecutable);
751
752 #if KASLR_KEXT_DEBUG
753 IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu vm_kernel_slide %llu (0x%016lx) \n",
754 (unsigned long)kernelStart,
755 (unsigned long)getlastaddr(),
756 kernelLength,
757 vm_kernel_slide, vm_kernel_slide);
758 #endif
759
760 sKernelKext->loadTag = sNextLoadTag++; // the kernel is load tag 0
761 sKernelKext->bundleID = OSSymbol::withCString(kOSKextKernelIdentifier);
762
763 sKernelKext->version = OSKextParseVersionString(osrelease);
764 sKernelKext->compatibleVersion = sKernelKext->version;
765 sKernelKext->linkedExecutable = kernelExecutable;
766 sKernelKext->interfaceUUID = sKernelKext->copyUUID();
767
768 sKernelKext->flags.hasAllDependencies = 1;
769 sKernelKext->flags.kernelComponent = 1;
770 sKernelKext->flags.prelinked = 0;
771 sKernelKext->flags.loaded = 1;
772 sKernelKext->flags.started = 1;
773 sKernelKext->flags.CPPInitialized = 0;
774 sKernelKext->flags.jettisonLinkeditSeg = 0;
775
776 sKernelKext->kmod_info = &g_kernel_kmod_info;
777 strlcpy(g_kernel_kmod_info.version, osrelease,
778 sizeof(g_kernel_kmod_info.version));
779 g_kernel_kmod_info.size = kernelLength;
780 g_kernel_kmod_info.id = sKernelKext->loadTag;
781
782 /* Cons up an info dict, so we don't have to have special-case
783 * checking all over.
784 */
785 sKernelKext->infoDict = OSDictionary::withCapacity(5);
786 assert(sKernelKext->infoDict);
787 setResult = sKernelKext->infoDict->setObject(kCFBundleIdentifierKey,
788 sKernelKext->bundleID);
789 assert(setResult);
790 setResult = sKernelKext->infoDict->setObject(kOSKernelResourceKey,
791 kOSBooleanTrue);
792 assert(setResult);
793
794 scratchString = OSString::withCStringNoCopy(osrelease);
795 assert(scratchString);
796 setResult = sKernelKext->infoDict->setObject(kCFBundleVersionKey,
797 scratchString);
798 assert(setResult);
799 OSSafeReleaseNULL(scratchString);
800
801 scratchString = OSString::withCStringNoCopy("mach_kernel");
802 assert(scratchString);
803 setResult = sKernelKext->infoDict->setObject(kCFBundleNameKey,
804 scratchString);
805 assert(setResult);
806 OSSafeReleaseNULL(scratchString);
807
808 /* Add the kernel kext to the bookkeeping dictionaries. Note that
809 * the kernel kext doesn't have a kmod_info struct. copyInfo()
810 * gathers info from other places anyhow.
811 */
812 setResult = sKextsByID->setObject(sKernelKext->bundleID, sKernelKext);
813 assert(setResult);
814 setResult = sLoadedKexts->setObject(sKernelKext);
815 assert(setResult);
816 sKernelKext->release();
817
818 registryRoot = IORegistryEntry::getRegistryRoot();
819 kernelCPUType = OSNumber::withNumber(
820 (long long unsigned int)_mh_execute_header.cputype,
821 8 * sizeof(_mh_execute_header.cputype));
822 kernelCPUSubtype = OSNumber::withNumber(
823 (long long unsigned int)_mh_execute_header.cpusubtype,
824 8 * sizeof(_mh_execute_header.cpusubtype));
825 assert(registryRoot && kernelCPUSubtype && kernelCPUType);
826
827 registryRoot->setProperty(kOSKernelCPUTypeKey, kernelCPUType);
828 registryRoot->setProperty(kOSKernelCPUSubtypeKey, kernelCPUSubtype);
829
830 OSSafeReleaseNULL(kernelCPUType);
831 OSSafeReleaseNULL(kernelCPUSubtype);
832
833 gBuiltinKmodsSectionInfo = getsectbyname(kPrelinkInfoSegment, kBuiltinInfoSection);
834 if (gBuiltinKmodsSectionInfo) {
835 uint32_t count;
836
837 assert(gBuiltinKmodsSectionInfo->addr);
838 assert(gBuiltinKmodsSectionInfo->size);
839 gBuiltinKmodsCount = (gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *));
840
841 gBuiltinKmodsSectionStart = getsectbyname(kPrelinkInfoSegment, kBuiltinStartSection);
842 assert(gBuiltinKmodsSectionStart);
843 assert(gBuiltinKmodsSectionStart->addr);
844 assert(gBuiltinKmodsSectionStart->size);
845 count = (gBuiltinKmodsSectionStart->size / sizeof(uintptr_t));
846 // one extra pointer for the end of last kmod
847 assert(count == (gBuiltinKmodsCount + 1));
848
849 vm_kernel_builtinkmod_text = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[0];
850 vm_kernel_builtinkmod_text_end = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[count - 1];
851 }
852 gIOSurfaceIdentifier = OSSymbol::withCStringNoCopy("com.apple.iokit.IOSurface");
853
854 timestamp = __OSAbsoluteTimePtr(&last_loaded_timestamp);
855 *timestamp = 0;
856 timestamp = __OSAbsoluteTimePtr(&last_unloaded_timestamp);
857 *timestamp = 0;
858 timestamp = __OSAbsoluteTimePtr(&sLastWakeTime);
859 *timestamp = 0;
860
861 OSKextLog(/* kext */ NULL,
862 kOSKextLogProgressLevel |
863 kOSKextLogGeneralFlag,
864 "Kext system initialized.");
865
866 notifyKextLoadObservers(sKernelKext, sKernelKext->kmod_info);
867
868 return;
869 }
870
871 /*********************************************************************
872 * This is expected to be called exactly once, from exactly one thread
873 * context, during kernel bootstrap.
874 *********************************************************************/
875 /* static */
876 OSReturn
877 OSKext::removeKextBootstrap(void)
878 {
879 OSReturn result = kOSReturnError;
880
881 const char * dt_kernel_header_name = "Kernel-__HEADER";
882 const char * dt_kernel_symtab_name = "Kernel-__SYMTAB";
883 kernel_mach_header_t * dt_mach_header = NULL;
884 int dt_mach_header_size = 0;
885 struct symtab_command * dt_symtab = NULL;
886 int dt_symtab_size = 0;
887 int dt_result = 0;
888
889 kernel_segment_command_t * seg_to_remove = NULL;
890
891 #if __arm__ || __arm64__
892 const char * dt_segment_name = NULL;
893 void * segment_paddress = NULL;
894 int segment_size = 0;
895 #endif
896
897 OSKextLog(/* kext */ NULL,
898 kOSKextLogProgressLevel |
899 kOSKextLogGeneralFlag,
900 "Jettisoning kext bootstrap segments.");
901
902 /*****
903 * Dispose of unnecessary stuff that the booter didn't need to load.
904 */
905 dt_result = IODTGetLoaderInfo(dt_kernel_header_name,
906 (void **)&dt_mach_header, &dt_mach_header_size);
907 if (dt_result == 0 && dt_mach_header) {
908 IODTFreeLoaderInfo(dt_kernel_header_name, (void *)dt_mach_header,
909 round_page_32(dt_mach_header_size));
910 }
911 dt_result = IODTGetLoaderInfo(dt_kernel_symtab_name,
912 (void **)&dt_symtab, &dt_symtab_size);
913 if (dt_result == 0 && dt_symtab) {
914 IODTFreeLoaderInfo(dt_kernel_symtab_name, (void *)dt_symtab,
915 round_page_32(dt_symtab_size));
916 }
917
918 /*****
919 * KLD bootstrap segment.
920 */
921 // xxx - should rename KLD segment
922 seg_to_remove = getsegbyname("__KLD");
923 if (seg_to_remove) {
924 OSRuntimeUnloadCPPForSegment(seg_to_remove);
925 }
926
927 #if __arm__ || __arm64__
928 /* Free the memory that was set up by bootx.
929 */
930 dt_segment_name = "Kernel-__KLD";
931 if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
932 /* We cannot free this with KTRR enabled, as we cannot
933 * update the permissions on the KLD range this late
934 * in the boot process.
935 */
936 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
937 (int)segment_size);
938 }
939 #elif __i386__ || __x86_64__
940 /* On x86, use the mapping data from the segment load command to
941 * unload KLD directly.
942 * This may invalidate any assumptions about "avail_start"
943 * defining the lower bound for valid physical addresses.
944 */
945 if (seg_to_remove && seg_to_remove->vmaddr && seg_to_remove->vmsize) {
946 // 04/18/11 - gab: <rdar://problem/9236163>
947 // overwrite memory occupied by KLD segment with random data before
948 // releasing it.
949 read_frandom((void *) seg_to_remove->vmaddr, seg_to_remove->vmsize);
950 ml_static_mfree(seg_to_remove->vmaddr, seg_to_remove->vmsize);
951 }
952 #else
953 #error arch
954 #endif
955
956 seg_to_remove = NULL;
957
958 /*****
959 * Prelinked kernel's symtab (if there is one).
960 */
961 kernel_section_t * sect;
962 sect = getsectbyname("__PRELINK", "__symtab");
963 if (sect && sect->addr && sect->size) {
964 ml_static_mfree(sect->addr, sect->size);
965 }
966
967 seg_to_remove = (kernel_segment_command_t *)getsegbyname("__LINKEDIT");
968
969 /* kxld always needs the kernel's __LINKEDIT segment, but we can make it
970 * pageable, unless keepsyms is set. To do that, we have to copy it from
971 * its booter-allocated memory, free the booter memory, reallocate proper
972 * managed memory, then copy the segment back in.
973 */
974 #if CONFIG_KXLD
975 #if (__arm__ || __arm64__)
976 #error CONFIG_KXLD not expected for this arch
977 #endif
978 if (!sKeepSymbols) {
979 kern_return_t mem_result;
980 void *seg_copy = NULL;
981 void *seg_data = NULL;
982 vm_map_offset_t seg_offset = 0;
983 vm_map_offset_t seg_copy_offset = 0;
984 vm_map_size_t seg_length = 0;
985
986 seg_data = (void *) seg_to_remove->vmaddr;
987 seg_offset = (vm_map_offset_t) seg_to_remove->vmaddr;
988 seg_length = (vm_map_size_t) seg_to_remove->vmsize;
989
990 /* Allocate space for the LINKEDIT copy.
991 */
992 mem_result = kmem_alloc(kernel_map, (vm_offset_t *) &seg_copy,
993 seg_length, VM_KERN_MEMORY_KEXT);
994 if (mem_result != KERN_SUCCESS) {
995 OSKextLog(/* kext */ NULL,
996 kOSKextLogErrorLevel |
997 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
998 "Can't copy __LINKEDIT segment for VM reassign.");
999 return result;
1000 }
1001 seg_copy_offset = (vm_map_offset_t) seg_copy;
1002
1003 /* Copy it out.
1004 */
1005 memcpy(seg_copy, seg_data, seg_length);
1006
1007 /* Dump the booter memory.
1008 */
1009 ml_static_mfree(seg_offset, seg_length);
1010
1011 /* Set up the VM region.
1012 */
1013 mem_result = vm_map_enter_mem_object(
1014 kernel_map,
1015 &seg_offset,
1016 seg_length, /* mask */ 0,
1017 VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE,
1018 VM_MAP_KERNEL_FLAGS_NONE,
1019 VM_KERN_MEMORY_NONE,
1020 (ipc_port_t)NULL,
1021 (vm_object_offset_t) 0,
1022 /* copy */ FALSE,
1023 /* cur_protection */ VM_PROT_READ | VM_PROT_WRITE,
1024 /* max_protection */ VM_PROT_ALL,
1025 /* inheritance */ VM_INHERIT_DEFAULT);
1026 if ((mem_result != KERN_SUCCESS) ||
1027 (seg_offset != (vm_map_offset_t) seg_data)) {
1028 OSKextLog(/* kext */ NULL,
1029 kOSKextLogErrorLevel |
1030 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1031 "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).",
1032 seg_data, seg_length, mem_result);
1033 return result;
1034 }
1035
1036 /* And copy it back.
1037 */
1038 memcpy(seg_data, seg_copy, seg_length);
1039
1040 /* Free the copy.
1041 */
1042 kmem_free(kernel_map, seg_copy_offset, seg_length);
1043 }
1044 #else /* we are not CONFIG_KXLD */
1045 #if !(__arm__ || __arm64__)
1046 #error CONFIG_KXLD is expected for this arch
1047 #endif
1048
1049 /*****
1050 * Dump the LINKEDIT segment, unless keepsyms is set.
1051 */
1052 if (!sKeepSymbols) {
1053 dt_segment_name = "Kernel-__LINKEDIT";
1054 if (0 == IODTGetLoaderInfo(dt_segment_name,
1055 &segment_paddress, &segment_size)) {
1056 #ifdef SECURE_KERNEL
1057 vm_offset_t vmaddr = ml_static_ptovirt((vm_offset_t)segment_paddress);
1058 bzero((void*)vmaddr, segment_size);
1059 #endif
1060 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1061 (int)segment_size);
1062 }
1063 } else {
1064 OSKextLog(/* kext */ NULL,
1065 kOSKextLogBasicLevel |
1066 kOSKextLogGeneralFlag,
1067 "keepsyms boot arg specified; keeping linkedit segment for symbols.");
1068 }
1069 #endif /* CONFIG_KXLD */
1070
1071 seg_to_remove = NULL;
1072
1073 result = kOSReturnSuccess;
1074
1075 return result;
1076 }
1077
1078 /*********************************************************************
1079 *********************************************************************/
1080 void
1081 OSKext::flushNonloadedKexts(
1082 Boolean flushPrelinkedKexts)
1083 {
1084 OSSet * prelinkedKexts = NULL;// must release
1085 OSCollectionIterator * kextIterator = NULL;// must release
1086 OSCollectionIterator * prelinkIterator = NULL; // must release
1087 const OSSymbol * thisID = NULL;// do not release
1088 OSKext * thisKext = NULL;// do not release
1089 uint32_t count, i;
1090
1091 IORecursiveLockLock(sKextLock);
1092
1093 OSKextLog(/* kext */ NULL,
1094 kOSKextLogProgressLevel |
1095 kOSKextLogKextBookkeepingFlag,
1096 "Flushing nonloaded kexts and other unused data.");
1097
1098 OSKext::considerDestroyingLinkContext();
1099
1100 /* If we aren't flushing unused prelinked kexts, we have to put them
1101 * aside while we flush everything else so make a container for them.
1102 */
1103 if (!flushPrelinkedKexts) {
1104 prelinkedKexts = OSSet::withCapacity(0);
1105 if (!prelinkedKexts) {
1106 goto finish;
1107 }
1108 }
1109
1110 /* Set aside prelinked kexts (in-use or not) and break
1111 * any lingering inter-kext references for nonloaded kexts
1112 * so they have min. retain counts.
1113 */
1114 kextIterator = OSCollectionIterator::withCollection(sKextsByID);
1115 if (!kextIterator) {
1116 goto finish;
1117 }
1118
1119 while ((thisID = OSDynamicCast(OSSymbol,
1120 kextIterator->getNextObject()))) {
1121 thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
1122
1123 if (thisKext) {
1124 if (prelinkedKexts && thisKext->isPrelinked()) {
1125 prelinkedKexts->setObject(thisKext);
1126 }
1127 thisKext->flushDependencies(/* forceIfLoaded */ false);
1128 }
1129 }
1130
1131 /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
1132 */
1133 sKextsByID->flushCollection();
1134
1135 /* Now put the loaded kexts back into the ID dictionary.
1136 */
1137 count = sLoadedKexts->getCount();
1138 for (i = 0; i < count; i++) {
1139 thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
1140 sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1141 }
1142
1143 /* Finally, put back the prelinked kexts if we saved any.
1144 */
1145 if (prelinkedKexts) {
1146 prelinkIterator = OSCollectionIterator::withCollection(prelinkedKexts);
1147 if (!prelinkIterator) {
1148 goto finish;
1149 }
1150
1151 while ((thisKext = OSDynamicCast(OSKext,
1152 prelinkIterator->getNextObject()))) {
1153 sKextsByID->setObject(thisKext->getIdentifierCString(),
1154 thisKext);
1155 }
1156 }
1157
1158 finish:
1159 IORecursiveLockUnlock(sKextLock);
1160
1161 OSSafeReleaseNULL(prelinkedKexts);
1162 OSSafeReleaseNULL(kextIterator);
1163 OSSafeReleaseNULL(prelinkIterator);
1164
1165 return;
1166 }
1167
1168 /*********************************************************************
1169 *********************************************************************/
1170 /* static */
1171 void
1172 OSKext::setKextdActive(Boolean active)
1173 {
1174 IORecursiveLockLock(sKextLock);
1175 sKextdActive = active;
1176 if (sKernelRequests->getCount()) {
1177 OSKext::pingKextd();
1178 }
1179 IORecursiveLockUnlock(sKextLock);
1180
1181 return;
1182 }
1183
1184 /*********************************************************************
1185 * OSKextLib.cpp might need access to this someday but for now it's
1186 * private.
1187 *********************************************************************/
1188 extern "C" {
1189 extern void ipc_port_release_send(ipc_port_t);
1190 };
1191
1192 /* static */
1193 OSReturn
1194 OSKext::pingKextd(void)
1195 {
1196 OSReturn result = kOSReturnError;
1197 #if !NO_KEXTD
1198 mach_port_t kextd_port = IPC_PORT_NULL;
1199
1200 if (!sKextdActive) {
1201 result = kOSKextReturnDisabled; // basically unavailable
1202 goto finish;
1203 }
1204
1205 result = host_get_kextd_port(host_priv_self(), &kextd_port);
1206 if (result != KERN_SUCCESS || !IPC_PORT_VALID(kextd_port)) {
1207 OSKextLog(/* kext */ NULL,
1208 kOSKextLogErrorLevel |
1209 kOSKextLogIPCFlag,
1210 "Can't get kextd port.");
1211 goto finish;
1212 }
1213
1214 result = kextd_ping(kextd_port);
1215 if (result != KERN_SUCCESS) {
1216 OSKextLog(/* kext */ NULL,
1217 kOSKextLogErrorLevel |
1218 kOSKextLogIPCFlag,
1219 "kextd ping failed (0x%x).", (int)result);
1220 goto finish;
1221 }
1222
1223 finish:
1224 if (IPC_PORT_VALID(kextd_port)) {
1225 ipc_port_release_send(kextd_port);
1226 }
1227 #endif
1228
1229 return result;
1230 }
1231
1232 /*********************************************************************
1233 *********************************************************************/
1234 /* static */
1235 void
1236 OSKext::setDeferredLoadSucceeded(Boolean succeeded)
1237 {
1238 IORecursiveLockLock(sKextLock);
1239 sDeferredLoadSucceeded = succeeded;
1240 IORecursiveLockUnlock(sKextLock);
1241
1242 return;
1243 }
1244
1245 /*********************************************************************
1246 * Called from IOSystemShutdownNotification.
1247 *********************************************************************/
1248 /* static */
1249 void
1250 OSKext::willShutdown(void)
1251 {
1252 #if !NO_KEXTD
1253 OSReturn checkResult = kOSReturnError;
1254 #endif
1255 OSDictionary * exitRequest = NULL; // must release
1256
1257 IORecursiveLockLock(sKextLock);
1258
1259 OSKext::setLoadEnabled(false);
1260 OSKext::setUnloadEnabled(false);
1261 OSKext::setAutounloadsEnabled(false);
1262 OSKext::setKernelRequestsEnabled(false);
1263
1264 #if !NO_KEXTD
1265 OSKextLog(/* kext */ NULL,
1266 kOSKextLogProgressLevel |
1267 kOSKextLogGeneralFlag,
1268 "System shutdown; requesting immediate kextd exit.");
1269
1270 checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestKextdExit,
1271 &exitRequest);
1272 if (checkResult != kOSReturnSuccess) {
1273 goto finish;
1274 }
1275 if (!sKernelRequests->setObject(exitRequest)) {
1276 goto finish;
1277 }
1278
1279 OSKext::pingKextd();
1280
1281 finish:
1282 #endif
1283
1284 IORecursiveLockUnlock(sKextLock);
1285
1286 OSSafeReleaseNULL(exitRequest);
1287 return;
1288 }
1289
1290 /*********************************************************************
1291 *********************************************************************/
1292 /* static */
1293 bool
1294 OSKext::getLoadEnabled(void)
1295 {
1296 bool result;
1297
1298 IORecursiveLockLock(sKextLock);
1299 result = sLoadEnabled;
1300 IORecursiveLockUnlock(sKextLock);
1301 return result;
1302 }
1303
1304 /*********************************************************************
1305 *********************************************************************/
1306 /* static */
1307 bool
1308 OSKext::setLoadEnabled(bool flag)
1309 {
1310 bool result;
1311
1312 IORecursiveLockLock(sKextLock);
1313 result = sLoadEnabled;
1314 sLoadEnabled = (flag ? true : false);
1315
1316 if (sLoadEnabled != result) {
1317 OSKextLog(/* kext */ NULL,
1318 kOSKextLogBasicLevel |
1319 kOSKextLogLoadFlag,
1320 "Kext loading now %sabled.", sLoadEnabled ? "en" : "dis");
1321 }
1322
1323 IORecursiveLockUnlock(sKextLock);
1324
1325 return result;
1326 }
1327
1328 /*********************************************************************
1329 *********************************************************************/
1330 /* static */
1331 bool
1332 OSKext::getUnloadEnabled(void)
1333 {
1334 bool result;
1335
1336 IORecursiveLockLock(sKextLock);
1337 result = sUnloadEnabled;
1338 IORecursiveLockUnlock(sKextLock);
1339 return result;
1340 }
1341
1342 /*********************************************************************
1343 *********************************************************************/
1344 /* static */
1345 bool
1346 OSKext::setUnloadEnabled(bool flag)
1347 {
1348 bool result;
1349
1350 IORecursiveLockLock(sKextLock);
1351 result = sUnloadEnabled;
1352 sUnloadEnabled = (flag ? true : false);
1353 IORecursiveLockUnlock(sKextLock);
1354
1355 if (sUnloadEnabled != result) {
1356 OSKextLog(/* kext */ NULL,
1357 kOSKextLogBasicLevel |
1358 kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1359 "Kext unloading now %sabled.", sUnloadEnabled ? "en" : "dis");
1360 }
1361
1362 return result;
1363 }
1364
1365 /*********************************************************************
1366 * Do not call any function that takes sKextLock here!
1367 *********************************************************************/
1368 /* static */
1369 bool
1370 OSKext::getAutounloadEnabled(void)
1371 {
1372 bool result;
1373
1374 IORecursiveLockLock(sKextInnerLock);
1375 result = sAutounloadEnabled ? true : false;
1376 IORecursiveLockUnlock(sKextInnerLock);
1377 return result;
1378 }
1379
1380 /*********************************************************************
1381 * Do not call any function that takes sKextLock here!
1382 *********************************************************************/
1383 /* static */
1384 bool
1385 OSKext::setAutounloadsEnabled(bool flag)
1386 {
1387 bool result;
1388
1389 IORecursiveLockLock(sKextInnerLock);
1390
1391 result = sAutounloadEnabled;
1392 sAutounloadEnabled = (flag ? true : false);
1393 if (!sAutounloadEnabled && sUnloadCallout) {
1394 thread_call_cancel(sUnloadCallout);
1395 }
1396
1397 if (sAutounloadEnabled != result) {
1398 OSKextLog(/* kext */ NULL,
1399 kOSKextLogBasicLevel |
1400 kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1401 "Kext autounloading now %sabled.",
1402 sAutounloadEnabled ? "en" : "dis");
1403 }
1404
1405 IORecursiveLockUnlock(sKextInnerLock);
1406
1407 return result;
1408 }
1409
1410 /*********************************************************************
1411 *********************************************************************/
1412 /* instance method operating on OSKext field */
1413 bool
1414 OSKext::setAutounloadEnabled(bool flag)
1415 {
1416 bool result = flags.autounloadEnabled ? true : false;
1417 flags.autounloadEnabled = flag ? 1 : 0;
1418
1419 if (result != (flag ? true : false)) {
1420 OSKextLog(this,
1421 kOSKextLogProgressLevel |
1422 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
1423 "Autounloading for kext %s now %sabled.",
1424 getIdentifierCString(),
1425 flags.autounloadEnabled ? "en" : "dis");
1426 }
1427 return result;
1428 }
1429
1430 /*********************************************************************
1431 *********************************************************************/
1432 /* static */
1433 bool
1434 OSKext::setKernelRequestsEnabled(bool flag)
1435 {
1436 bool result;
1437
1438 IORecursiveLockLock(sKextLock);
1439 result = sKernelRequestsEnabled;
1440 sKernelRequestsEnabled = flag ? true : false;
1441
1442 if (sKernelRequestsEnabled != result) {
1443 OSKextLog(/* kext */ NULL,
1444 kOSKextLogBasicLevel |
1445 kOSKextLogGeneralFlag,
1446 "Kernel requests now %sabled.",
1447 sKernelRequestsEnabled ? "en" : "dis");
1448 }
1449 IORecursiveLockUnlock(sKextLock);
1450 return result;
1451 }
1452
1453 /*********************************************************************
1454 *********************************************************************/
1455 /* static */
1456 bool
1457 OSKext::getKernelRequestsEnabled(void)
1458 {
1459 bool result;
1460
1461 IORecursiveLockLock(sKextLock);
1462 result = sKernelRequestsEnabled;
1463 IORecursiveLockUnlock(sKextLock);
1464 return result;
1465 }
1466
1467 #if PRAGMA_MARK
1468 #pragma mark Kext Life Cycle
1469 #endif
1470 /*********************************************************************
1471 *********************************************************************/
1472 OSKext *
1473 OSKext::withPrelinkedInfoDict(
1474 OSDictionary * anInfoDict,
1475 bool doCoalesedSlides)
1476 {
1477 OSKext * newKext = new OSKext;
1478
1479 if (newKext && !newKext->initWithPrelinkedInfoDict(anInfoDict, doCoalesedSlides)) {
1480 newKext->release();
1481 return NULL;
1482 }
1483
1484 return newKext;
1485 }
1486
1487 /*********************************************************************
1488 *********************************************************************/
1489 bool
1490 OSKext::initWithPrelinkedInfoDict(
1491 OSDictionary * anInfoDict,
1492 bool doCoalesedSlides)
1493 {
1494 bool result = false;
1495 OSString * kextPath = NULL;// do not release
1496 OSNumber * addressNum = NULL;// reused; do not release
1497 OSNumber * lengthNum = NULL;// reused; do not release
1498 void * data = NULL;// do not free
1499 void * srcData = NULL;// do not free
1500 OSData * prelinkedExecutable = NULL;// must release
1501 uint32_t length = 0; // reused
1502
1503 if (!super::init()) {
1504 goto finish;
1505 }
1506
1507 /* Get the path. Don't look for an arch-specific path property.
1508 */
1509 kextPath = OSDynamicCast(OSString,
1510 anInfoDict->getObject(kPrelinkBundlePathKey));
1511
1512 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
1513 goto finish;
1514 }
1515 #if KASLR_KEXT_DEBUG
1516 IOLog("kaslr: doCoalesedSlides %d kext %s \n", doCoalesedSlides, getIdentifierCString());
1517 #endif
1518
1519 /* Also get the executable's bundle-relative path if present.
1520 * Don't look for an arch-specific path property.
1521 */
1522 executableRelPath = OSDynamicCast(OSString,
1523 anInfoDict->getObject(kPrelinkExecutableRelativePathKey));
1524 if (executableRelPath) {
1525 executableRelPath->retain();
1526 }
1527
1528 /* Don't need the paths to be in the info dictionary any more.
1529 */
1530 anInfoDict->removeObject(kPrelinkBundlePathKey);
1531 anInfoDict->removeObject(kPrelinkExecutableRelativePathKey);
1532
1533 /* Create an OSData wrapper around the linked executable.
1534 */
1535 addressNum = OSDynamicCast(OSNumber,
1536 anInfoDict->getObject(kPrelinkExecutableLoadKey));
1537 if (addressNum) {
1538 lengthNum = OSDynamicCast(OSNumber,
1539 anInfoDict->getObject(kPrelinkExecutableSizeKey));
1540 if (!lengthNum) {
1541 OSKextLog(this,
1542 kOSKextLogErrorLevel |
1543 kOSKextLogArchiveFlag,
1544 "Kext %s can't find prelinked kext executable size.",
1545 getIdentifierCString());
1546 goto finish;
1547 }
1548
1549 data = (void *) ml_static_slide((intptr_t) (addressNum->unsigned64BitValue()));
1550 length = (uint32_t) (lengthNum->unsigned32BitValue());
1551
1552 #if KASLR_KEXT_DEBUG
1553 IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",
1554 (unsigned long)ml_static_unslide(data),
1555 (unsigned long)data,
1556 length);
1557 #endif
1558
1559 anInfoDict->removeObject(kPrelinkExecutableLoadKey);
1560 anInfoDict->removeObject(kPrelinkExecutableSizeKey);
1561
1562 /* If the kext's load address differs from its source address, allocate
1563 * space in the kext map at the load address and copy the kext over.
1564 */
1565 addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject(kPrelinkExecutableSourceKey));
1566 if (addressNum) {
1567 srcData = (void *) ml_static_slide((intptr_t) (addressNum->unsigned64BitValue()));
1568
1569 #if KASLR_KEXT_DEBUG
1570 IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
1571 (unsigned long)ml_static_unslide(srcData),
1572 (unsigned long)srcData);
1573 #endif
1574
1575 if (data != srcData) {
1576 #if __LP64__
1577 kern_return_t alloc_result;
1578
1579 alloc_result = kext_alloc((vm_offset_t *)&data, length, /* fixed */ TRUE);
1580 if (alloc_result != KERN_SUCCESS) {
1581 OSKextLog(this,
1582 kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
1583 "Failed to allocate space for prelinked kext %s.",
1584 getIdentifierCString());
1585 goto finish;
1586 }
1587 memcpy(data, srcData, length);
1588 #else
1589 OSKextLog(this,
1590 kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
1591 "Error: prelinked kext %s - source and load addresses "
1592 "differ on ILP32 architecture.",
1593 getIdentifierCString());
1594 goto finish;
1595 #endif /* __LP64__ */
1596 }
1597
1598 anInfoDict->removeObject(kPrelinkExecutableSourceKey);
1599 }
1600
1601 prelinkedExecutable = OSData::withBytesNoCopy(data, length);
1602 if (!prelinkedExecutable) {
1603 OSKextLog(this,
1604 kOSKextLogErrorLevel |
1605 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1606 "Kext %s failed to create executable wrapper.",
1607 getIdentifierCString());
1608 goto finish;
1609 }
1610
1611 #if VM_MAPPED_KEXTS
1612 prelinkedExecutable->setDeallocFunction(osdata_kext_free);
1613 #else
1614 prelinkedExecutable->setDeallocFunction(osdata_phys_free);
1615 #endif
1616 setLinkedExecutable(prelinkedExecutable);
1617 addressNum = OSDynamicCast(OSNumber,
1618 anInfoDict->getObject(kPrelinkKmodInfoKey));
1619 if (!addressNum) {
1620 OSKextLog(this,
1621 kOSKextLogErrorLevel |
1622 kOSKextLogArchiveFlag,
1623 "Kext %s can't find prelinked kext kmod_info address.",
1624 getIdentifierCString());
1625 goto finish;
1626 }
1627
1628 if (addressNum->unsigned64BitValue() != 0) {
1629 kmod_info = (kmod_info_t *) ml_static_slide((intptr_t) (addressNum->unsigned64BitValue()));
1630 kmod_info->address = ml_static_slide(kmod_info->address);
1631 #if KASLR_KEXT_DEBUG
1632 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
1633 (unsigned long)ml_static_unslide(kmod_info),
1634 (unsigned long)kmod_info);
1635 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
1636 (unsigned long)ml_static_unslide(kmod_info->address),
1637 (unsigned long)kmod_info->address);
1638 #endif
1639 }
1640
1641 anInfoDict->removeObject(kPrelinkKmodInfoKey);
1642 }
1643
1644 if ((addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject("ModuleIndex")))) {
1645 uintptr_t builtinTextStart;
1646 uintptr_t builtinTextEnd;
1647
1648 flags.builtin = true;
1649 builtinKmodIdx = addressNum->unsigned32BitValue();
1650 assert(builtinKmodIdx < gBuiltinKmodsCount);
1651
1652 builtinTextStart = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx];
1653 builtinTextEnd = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx + 1];
1654
1655 kmod_info = ((kmod_info_t **)gBuiltinKmodsSectionInfo->addr)[builtinKmodIdx];
1656 kmod_info->address = builtinTextStart;
1657 kmod_info->size = builtinTextEnd - builtinTextStart;
1658 }
1659
1660 /* If the plist has a UUID for an interface, save that off.
1661 */
1662 if (isInterface()) {
1663 interfaceUUID = OSDynamicCast(OSData,
1664 anInfoDict->getObject(kPrelinkInterfaceUUIDKey));
1665 if (interfaceUUID) {
1666 interfaceUUID->retain();
1667 anInfoDict->removeObject(kPrelinkInterfaceUUIDKey);
1668 }
1669 }
1670
1671 result = slidePrelinkedExecutable(doCoalesedSlides);
1672 if (result != kOSReturnSuccess) {
1673 goto finish;
1674 }
1675
1676 if (doCoalesedSlides == false) {
1677 /* set VM protections now, wire later at kext load */
1678 result = setVMAttributes(true, false);
1679 if (result != KERN_SUCCESS) {
1680 goto finish;
1681 }
1682 }
1683
1684 flags.prelinked = true;
1685
1686 /* If we created a kext from prelink info,
1687 * we must be booting from a prelinked kernel.
1688 */
1689 sPrelinkBoot = true;
1690
1691 result = registerIdentifier();
1692
1693 finish:
1694 OSSafeReleaseNULL(prelinkedExecutable);
1695
1696 return result;
1697 }
1698
1699 /*********************************************************************
1700 *********************************************************************/
1701 /* static */
1702 void
1703 OSKext::setAllVMAttributes(void)
1704 {
1705 OSCollectionIterator * kextIterator = NULL;// must release
1706 const OSSymbol * thisID = NULL;// do not release
1707
1708 IORecursiveLockLock(sKextLock);
1709
1710 kextIterator = OSCollectionIterator::withCollection(sKextsByID);
1711 if (!kextIterator) {
1712 goto finish;
1713 }
1714
1715 while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
1716 OSKext * thisKext;// do not release
1717
1718 thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
1719 if (!thisKext || thisKext->isInterface() || !thisKext->declaresExecutable()) {
1720 continue;
1721 }
1722
1723 /* set VM protections now, wire later at kext load */
1724 thisKext->setVMAttributes(true, false);
1725 }
1726
1727 finish:
1728 IORecursiveLockUnlock(sKextLock);
1729 OSSafeReleaseNULL(kextIterator);
1730
1731 return;
1732 }
1733
1734 /*********************************************************************
1735 *********************************************************************/
1736 OSKext *
1737 OSKext::withBooterData(
1738 OSString * deviceTreeName,
1739 OSData * booterData)
1740 {
1741 OSKext * newKext = new OSKext;
1742
1743 if (newKext && !newKext->initWithBooterData(deviceTreeName, booterData)) {
1744 newKext->release();
1745 return NULL;
1746 }
1747
1748 return newKext;
1749 }
1750
1751 /*********************************************************************
1752 *********************************************************************/
1753 typedef struct _BooterKextFileInfo {
1754 uint32_t infoDictPhysAddr;
1755 uint32_t infoDictLength;
1756 uint32_t executablePhysAddr;
1757 uint32_t executableLength;
1758 uint32_t bundlePathPhysAddr;
1759 uint32_t bundlePathLength;
1760 } _BooterKextFileInfo;
1761
1762 bool
1763 OSKext::initWithBooterData(
1764 OSString * deviceTreeName,
1765 OSData * booterData)
1766 {
1767 bool result = false;
1768 _BooterKextFileInfo * kextFileInfo = NULL;// do not free
1769 char * infoDictAddr = NULL;// do not free
1770 void * executableAddr = NULL;// do not free
1771 char * bundlePathAddr = NULL;// do not free
1772
1773 OSObject * parsedXML = NULL;// must release
1774 OSDictionary * theInfoDict = NULL;// do not release
1775 OSString * kextPath = NULL;// must release
1776 OSString * errorString = NULL;// must release
1777 OSData * executable = NULL;// must release
1778
1779 if (!super::init()) {
1780 goto finish;
1781 }
1782
1783 kextFileInfo = (_BooterKextFileInfo *)booterData->getBytesNoCopy();
1784 if (!kextFileInfo) {
1785 OSKextLog(this,
1786 kOSKextLogErrorLevel |
1787 kOSKextLogGeneralFlag,
1788 "No booter-provided data for kext device tree entry %s.",
1789 deviceTreeName->getCStringNoCopy());
1790 goto finish;
1791 }
1792
1793 /* The info plist must exist or we can't read the kext.
1794 */
1795 if (!kextFileInfo->infoDictPhysAddr || !kextFileInfo->infoDictLength) {
1796 OSKextLog(this,
1797 kOSKextLogErrorLevel |
1798 kOSKextLogGeneralFlag,
1799 "No kext info dictionary for booter device tree entry %s.",
1800 deviceTreeName->getCStringNoCopy());
1801 goto finish;
1802 }
1803
1804 infoDictAddr = (char *)ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
1805 if (!infoDictAddr) {
1806 OSKextLog(this,
1807 kOSKextLogErrorLevel |
1808 kOSKextLogGeneralFlag,
1809 "Can't translate physical address 0x%x of kext info dictionary "
1810 "for device tree entry %s.",
1811 (int)kextFileInfo->infoDictPhysAddr,
1812 deviceTreeName->getCStringNoCopy());
1813 goto finish;
1814 }
1815
1816 parsedXML = OSUnserializeXML(infoDictAddr, &errorString);
1817 if (parsedXML) {
1818 theInfoDict = OSDynamicCast(OSDictionary, parsedXML);
1819 }
1820 if (!theInfoDict) {
1821 const char * errorCString = "(unknown error)";
1822
1823 if (errorString && errorString->getCStringNoCopy()) {
1824 errorCString = errorString->getCStringNoCopy();
1825 } else if (parsedXML) {
1826 errorCString = "not a dictionary";
1827 }
1828 OSKextLog(this,
1829 kOSKextLogErrorLevel |
1830 kOSKextLogGeneralFlag,
1831 "Error unserializing info dictionary for device tree entry %s: %s.",
1832 deviceTreeName->getCStringNoCopy(), errorCString);
1833 goto finish;
1834 }
1835
1836 /* A bundle path is not mandatory.
1837 */
1838 if (kextFileInfo->bundlePathPhysAddr && kextFileInfo->bundlePathLength) {
1839 bundlePathAddr = (char *)ml_static_ptovirt(kextFileInfo->bundlePathPhysAddr);
1840 if (!bundlePathAddr) {
1841 OSKextLog(this,
1842 kOSKextLogErrorLevel |
1843 kOSKextLogGeneralFlag,
1844 "Can't translate physical address 0x%x of kext bundle path "
1845 "for device tree entry %s.",
1846 (int)kextFileInfo->bundlePathPhysAddr,
1847 deviceTreeName->getCStringNoCopy());
1848 goto finish;
1849 }
1850 bundlePathAddr[kextFileInfo->bundlePathLength - 1] = '\0'; // just in case!
1851
1852 kextPath = OSString::withCString(bundlePathAddr);
1853 if (!kextPath) {
1854 OSKextLog(this,
1855 kOSKextLogErrorLevel |
1856 kOSKextLogGeneralFlag,
1857 "Failed to create wrapper for device tree entry %s kext path %s.",
1858 deviceTreeName->getCStringNoCopy(), bundlePathAddr);
1859 goto finish;
1860 }
1861 }
1862
1863 if (!setInfoDictionaryAndPath(theInfoDict, kextPath)) {
1864 goto finish;
1865 }
1866
1867 /* An executable is not mandatory.
1868 */
1869 if (kextFileInfo->executablePhysAddr && kextFileInfo->executableLength) {
1870 executableAddr = (void *)ml_static_ptovirt(kextFileInfo->executablePhysAddr);
1871 if (!executableAddr) {
1872 OSKextLog(this,
1873 kOSKextLogErrorLevel |
1874 kOSKextLogGeneralFlag,
1875 "Can't translate physical address 0x%x of kext executable "
1876 "for device tree entry %s.",
1877 (int)kextFileInfo->executablePhysAddr,
1878 deviceTreeName->getCStringNoCopy());
1879 goto finish;
1880 }
1881
1882 executable = OSData::withBytesNoCopy(executableAddr,
1883 kextFileInfo->executableLength);
1884 if (!executable) {
1885 OSKextLog(this,
1886 kOSKextLogErrorLevel |
1887 kOSKextLogGeneralFlag,
1888 "Failed to create executable wrapper for device tree entry %s.",
1889 deviceTreeName->getCStringNoCopy());
1890 goto finish;
1891 }
1892
1893 /* A kext with an executable needs to retain the whole booterData
1894 * object to keep the executable in memory.
1895 */
1896 if (!setExecutable(executable, booterData)) {
1897 OSKextLog(this,
1898 kOSKextLogErrorLevel |
1899 kOSKextLogGeneralFlag,
1900 "Failed to set kext executable for device tree entry %s.",
1901 deviceTreeName->getCStringNoCopy());
1902 goto finish;
1903 }
1904 }
1905
1906 result = registerIdentifier();
1907
1908 finish:
1909 OSSafeReleaseNULL(parsedXML);
1910 OSSafeReleaseNULL(kextPath);
1911 OSSafeReleaseNULL(errorString);
1912 OSSafeReleaseNULL(executable);
1913
1914 return result;
1915 }
1916
1917 /*********************************************************************
1918 *********************************************************************/
1919 bool
1920 OSKext::registerIdentifier(void)
1921 {
1922 bool result = false;
1923 OSKext * existingKext = NULL;// do not release
1924 bool existingIsLoaded = false;
1925 bool existingIsPrelinked = false;
1926 OSKextVersion newVersion = -1;
1927 OSKextVersion existingVersion = -1;
1928 char newVersionCString[kOSKextVersionMaxLength];
1929 char existingVersionCString[kOSKextVersionMaxLength];
1930 OSData * newUUID = NULL;// must release
1931 OSData * existingUUID = NULL;// must release
1932
1933 IORecursiveLockLock(sKextLock);
1934
1935 /* Get the new kext's version for checks & log messages.
1936 */
1937 newVersion = getVersion();
1938 OSKextVersionGetString(newVersion, newVersionCString,
1939 kOSKextVersionMaxLength);
1940
1941 /* If we don't have an existing kext with this identifier,
1942 * just record the new kext and we're done!
1943 */
1944 existingKext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID));
1945 if (!existingKext) {
1946 sKextsByID->setObject(bundleID, this);
1947 result = true;
1948 goto finish;
1949 }
1950
1951 /* Get the existing kext's version for checks & log messages.
1952 */
1953 existingVersion = existingKext->getVersion();
1954 OSKextVersionGetString(existingVersion,
1955 existingVersionCString, kOSKextVersionMaxLength);
1956
1957 existingIsLoaded = existingKext->isLoaded();
1958 existingIsPrelinked = existingKext->isPrelinked();
1959
1960 /* If we have a kext with this identifier that's already loaded/prelinked,
1961 * we can't use the new one, but let's be really thorough and check how
1962 * the two are related for a precise diagnostic log message.
1963 *
1964 * Note that user space can't find out about nonloaded prelinked kexts,
1965 * so in this case we log a message when new & existing are equivalent
1966 * at the step rather than warning level, because we are always going
1967 * be getting a copy of the kext in the user load request mkext.
1968 */
1969 if (existingIsLoaded || existingIsPrelinked) {
1970 bool sameVersion = (newVersion == existingVersion);
1971 bool sameExecutable = true; // assume true unless we have UUIDs
1972
1973 /* Only get the UUID if the existing kext is loaded. Doing so
1974 * might have to uncompress an mkext executable and we shouldn't
1975 * take that hit when neither kext is loaded.
1976 */
1977 newUUID = copyUUID();
1978 existingUUID = existingKext->copyUUID();
1979
1980 /* I'm entirely too paranoid about checking equivalence of executables,
1981 * but I remember nasty problems with it in the past.
1982 *
1983 * - If we have UUIDs for both kexts, compare them.
1984 * - If only one kext has a UUID, they're definitely different.
1985 */
1986 if (newUUID && existingUUID) {
1987 sameExecutable = newUUID->isEqualTo(existingUUID);
1988 } else if (newUUID || existingUUID) {
1989 sameExecutable = false;
1990 }
1991
1992 if (!newUUID && !existingUUID) {
1993 /* If there are no UUIDs, we can't really tell that the executables
1994 * are *different* without a lot of work; the loaded kext's
1995 * unrelocated executable is no longer around (and we never had it
1996 * in-kernel for a prelinked kext). We certainly don't want to do
1997 * a whole fake link for the new kext just to compare, either.
1998 */
1999
2000 OSKextVersionGetString(version, newVersionCString,
2001 sizeof(newVersionCString));
2002 OSKextLog(this,
2003 kOSKextLogWarningLevel |
2004 kOSKextLogKextBookkeepingFlag,
2005 "Notice - new kext %s, v%s matches %s kext "
2006 "but can't determine if executables are the same (no UUIDs).",
2007 getIdentifierCString(),
2008 newVersionCString,
2009 (existingIsLoaded ? "loaded" : "prelinked"));
2010 }
2011
2012 if (sameVersion && sameExecutable) {
2013 OSKextLog(this,
2014 (existingIsLoaded ? kOSKextLogWarningLevel : kOSKextLogStepLevel) |
2015 kOSKextLogKextBookkeepingFlag,
2016 "Refusing new kext %s, v%s: a %s copy is already present "
2017 "(same version and executable).",
2018 getIdentifierCString(), newVersionCString,
2019 (existingIsLoaded ? "loaded" : "prelinked"));
2020 } else {
2021 if (!sameVersion) {
2022 /* This condition is significant so log it under warnings.
2023 */
2024 OSKextLog(this,
2025 kOSKextLogWarningLevel |
2026 kOSKextLogKextBookkeepingFlag,
2027 "Refusing new kext %s, v%s: already have %s v%s.",
2028 getIdentifierCString(),
2029 newVersionCString,
2030 (existingIsLoaded ? "loaded" : "prelinked"),
2031 existingVersionCString);
2032 } else {
2033 /* This condition is significant so log it under warnings.
2034 */
2035 OSKextLog(this,
2036 kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag,
2037 "Refusing new kext %s, v%s: a %s copy with a different "
2038 "executable UUID is already present.",
2039 getIdentifierCString(), newVersionCString,
2040 (existingIsLoaded ? "loaded" : "prelinked"));
2041 }
2042 }
2043 goto finish;
2044 } /* if (existingIsLoaded || existingIsPrelinked) */
2045
2046 /* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
2047 * user loads are happening or if we're still in early boot. User agents are
2048 * supposed to resolve dependencies topside and include only the exact
2049 * kexts needed; so we always accept the new kext (in fact we should never
2050 * see an older unloaded copy hanging around).
2051 */
2052 if (sUserLoadsActive) {
2053 sKextsByID->setObject(bundleID, this);
2054 result = true;
2055
2056 OSKextLog(this,
2057 kOSKextLogStepLevel |
2058 kOSKextLogKextBookkeepingFlag,
2059 "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
2060 getIdentifierCString(),
2061 existingVersionCString,
2062 newVersionCString);
2063
2064 goto finish;
2065 }
2066
2067 /* During early boot, the kext with the highest version always wins out.
2068 * Prelinked kernels will never hit this, but mkexts and booter-read
2069 * kexts might have duplicates.
2070 */
2071 if (newVersion > existingVersion) {
2072 sKextsByID->setObject(bundleID, this);
2073 result = true;
2074
2075 OSKextLog(this,
2076 kOSKextLogStepLevel |
2077 kOSKextLogKextBookkeepingFlag,
2078 "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
2079 existingVersionCString,
2080 getIdentifierCString(),
2081 newVersionCString);
2082 } else {
2083 OSKextLog(this,
2084 kOSKextLogStepLevel |
2085 kOSKextLogKextBookkeepingFlag,
2086 "Kext %s is already registered with a higher/same version (v%s); "
2087 "dropping newly-added (v%s).",
2088 getIdentifierCString(),
2089 existingVersionCString,
2090 newVersionCString);
2091 }
2092
2093 /* result has been set appropriately by now. */
2094
2095 finish:
2096
2097 IORecursiveLockUnlock(sKextLock);
2098
2099 if (result) {
2100 OSKextLog(this,
2101 kOSKextLogStepLevel |
2102 kOSKextLogKextBookkeepingFlag,
2103 "Kext %s, v%s registered and available for loading.",
2104 getIdentifierCString(), newVersionCString);
2105 }
2106
2107 OSSafeReleaseNULL(newUUID);
2108 OSSafeReleaseNULL(existingUUID);
2109
2110 return result;
2111 }
2112
2113 /*********************************************************************
2114 * Does the bare minimum validation to look up a kext.
2115 * All other validation is done on the spot as needed.
2116 **********************************************************************/
2117 bool
2118 OSKext::setInfoDictionaryAndPath(
2119 OSDictionary * aDictionary,
2120 OSString * aPath)
2121 {
2122 bool result = false;
2123 OSString * bundleIDString = NULL;// do not release
2124 OSString * versionString = NULL;// do not release
2125 OSString * compatibleVersionString = NULL;// do not release
2126 const char * versionCString = NULL;// do not free
2127 const char * compatibleVersionCString = NULL;// do not free
2128 OSBoolean * scratchBool = NULL;// do not release
2129 OSDictionary * scratchDict = NULL;// do not release
2130
2131 if (infoDict) {
2132 panic("Attempt to set info dictionary on a kext "
2133 "that already has one (%s).",
2134 getIdentifierCString());
2135 }
2136
2137 if (!aDictionary || !OSDynamicCast(OSDictionary, aDictionary)) {
2138 goto finish;
2139 }
2140
2141 infoDict = aDictionary;
2142 infoDict->retain();
2143
2144 /* Check right away if the info dictionary has any log flags.
2145 */
2146 scratchBool = OSDynamicCast(OSBoolean,
2147 getPropertyForHostArch(kOSBundleEnableKextLoggingKey));
2148 if (scratchBool == kOSBooleanTrue) {
2149 flags.loggingEnabled = 1;
2150 }
2151
2152 /* The very next thing to get is the bundle identifier. Unlike
2153 * in user space, a kext with no bundle identifier gets axed
2154 * immediately.
2155 */
2156 bundleIDString = OSDynamicCast(OSString,
2157 getPropertyForHostArch(kCFBundleIdentifierKey));
2158 if (!bundleIDString) {
2159 OSKextLog(this,
2160 kOSKextLogErrorLevel |
2161 kOSKextLogValidationFlag,
2162 "CFBundleIdentifier missing/invalid type in kext %s.",
2163 aPath ? aPath->getCStringNoCopy() : "(unknown)");
2164 goto finish;
2165 }
2166 bundleID = OSSymbol::withString(bundleIDString);
2167 if (!bundleID) {
2168 OSKextLog(this,
2169 kOSKextLogErrorLevel |
2170 kOSKextLogValidationFlag,
2171 "Can't copy bundle identifier as symbol for kext %s.",
2172 bundleIDString->getCStringNoCopy());
2173 goto finish;
2174 }
2175
2176 /* Save the path if we got one (it should always be available but it's
2177 * just something nice to have for bookkeeping).
2178 */
2179 if (aPath) {
2180 path = aPath;
2181 path->retain();
2182 }
2183
2184 /*****
2185 * Minimal validation to initialize. We'll do other validation on the spot.
2186 */
2187 if (bundleID->getLength() >= KMOD_MAX_NAME) {
2188 OSKextLog(this,
2189 kOSKextLogErrorLevel |
2190 kOSKextLogValidationFlag,
2191 "Kext %s error - CFBundleIdentifier over max length %d.",
2192 getIdentifierCString(), KMOD_MAX_NAME - 1);
2193 goto finish;
2194 }
2195
2196 version = compatibleVersion = -1;
2197
2198 versionString = OSDynamicCast(OSString,
2199 getPropertyForHostArch(kCFBundleVersionKey));
2200 if (!versionString) {
2201 OSKextLog(this,
2202 kOSKextLogErrorLevel |
2203 kOSKextLogValidationFlag,
2204 "Kext %s error - CFBundleVersion missing/invalid type.",
2205 getIdentifierCString());
2206 goto finish;
2207 }
2208 versionCString = versionString->getCStringNoCopy();
2209 version = OSKextParseVersionString(versionCString);
2210 if (version < 0) {
2211 OSKextLog(this,
2212 kOSKextLogErrorLevel |
2213 kOSKextLogValidationFlag,
2214 "Kext %s error - CFBundleVersion bad value '%s'.",
2215 getIdentifierCString(), versionCString);
2216 goto finish;
2217 }
2218
2219 compatibleVersion = -1; // set to illegal value for kexts that don't have
2220
2221 compatibleVersionString = OSDynamicCast(OSString,
2222 getPropertyForHostArch(kOSBundleCompatibleVersionKey));
2223 if (compatibleVersionString) {
2224 compatibleVersionCString = compatibleVersionString->getCStringNoCopy();
2225 compatibleVersion = OSKextParseVersionString(compatibleVersionCString);
2226 if (compatibleVersion < 0) {
2227 OSKextLog(this,
2228 kOSKextLogErrorLevel |
2229 kOSKextLogValidationFlag,
2230 "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
2231 getIdentifierCString(), compatibleVersionCString);
2232 goto finish;
2233 }
2234
2235 if (compatibleVersion > version) {
2236 OSKextLog(this,
2237 kOSKextLogErrorLevel |
2238 kOSKextLogValidationFlag,
2239 "Kext %s error - %s %s > %s %s (must be <=).",
2240 getIdentifierCString(),
2241 kOSBundleCompatibleVersionKey, compatibleVersionCString,
2242 kCFBundleVersionKey, versionCString);
2243 goto finish;
2244 }
2245 }
2246
2247 /* Check to see if this kext is in exclude list */
2248 if (isInExcludeList()) {
2249 OSKextLog(this,
2250 kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
2251 "Kext %s is in exclude list, not loadable",
2252 getIdentifierCString());
2253 goto finish;
2254 }
2255
2256 /* Set flags for later use if the infoDict gets flushed. We only
2257 * check for true values, not false ones(!)
2258 */
2259 scratchBool = OSDynamicCast(OSBoolean,
2260 getPropertyForHostArch(kOSBundleIsInterfaceKey));
2261 if (scratchBool == kOSBooleanTrue) {
2262 flags.interface = 1;
2263 }
2264
2265 scratchBool = OSDynamicCast(OSBoolean,
2266 getPropertyForHostArch(kOSKernelResourceKey));
2267 if (scratchBool == kOSBooleanTrue) {
2268 flags.kernelComponent = 1;
2269 flags.interface = 1; // xxx - hm. the kernel itself isn't an interface...
2270 flags.started = 1;
2271
2272 /* A kernel component has one implicit dependency on the kernel.
2273 */
2274 flags.hasAllDependencies = 1;
2275 }
2276
2277 /* Make sure common string values in personalities are uniqued to OSSymbols.
2278 */
2279 scratchDict = OSDynamicCast(OSDictionary,
2280 getPropertyForHostArch(kIOKitPersonalitiesKey));
2281 if (scratchDict) {
2282 uniquePersonalityProperties(scratchDict);
2283 }
2284
2285 result = true;
2286
2287 finish:
2288
2289 return result;
2290 }
2291
2292 /*********************************************************************
2293 * Not used for prelinked kernel boot as there is no unrelocated
2294 * executable.
2295 *********************************************************************/
2296 bool
2297 OSKext::setExecutable(
2298 OSData * anExecutable,
2299 OSData * externalData,
2300 bool externalDataIsMkext)
2301 {
2302 bool result = false;
2303 const char * executableKey = NULL; // do not free
2304
2305 if (!anExecutable) {
2306 infoDict->removeObject(_kOSKextExecutableKey);
2307 infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
2308 infoDict->removeObject(_kOSKextExecutableExternalDataKey);
2309 result = true;
2310 goto finish;
2311 }
2312
2313 if (infoDict->getObject(_kOSKextExecutableKey) ||
2314 infoDict->getObject(_kOSKextMkextExecutableReferenceKey)) {
2315 panic("Attempt to set an executable on a kext "
2316 "that already has one (%s).",
2317 getIdentifierCString());
2318 goto finish;
2319 }
2320
2321 if (externalDataIsMkext) {
2322 executableKey = _kOSKextMkextExecutableReferenceKey;
2323 } else {
2324 executableKey = _kOSKextExecutableKey;
2325 }
2326
2327 if (anExecutable) {
2328 infoDict->setObject(executableKey, anExecutable);
2329 if (externalData) {
2330 infoDict->setObject(_kOSKextExecutableExternalDataKey, externalData);
2331 }
2332 }
2333
2334 result = true;
2335
2336 finish:
2337 return result;
2338 }
2339
2340 /*********************************************************************
2341 *********************************************************************/
2342 static void
2343 uniqueStringPlistProperty(OSDictionary * dict, const char * key)
2344 {
2345 OSString * stringValue = NULL;// do not release
2346 const OSSymbol * symbolValue = NULL; // must release
2347
2348 stringValue = OSDynamicCast(OSString, dict->getObject(key));
2349 if (!stringValue) {
2350 goto finish;
2351 }
2352
2353 symbolValue = OSSymbol::withString(stringValue);
2354 if (!symbolValue) {
2355 goto finish;
2356 }
2357
2358 dict->setObject(key, symbolValue);
2359
2360 finish:
2361 if (symbolValue) {
2362 symbolValue->release();
2363 }
2364
2365 return;
2366 }
2367
2368 /*********************************************************************
2369 *********************************************************************/
2370 static void
2371 uniqueStringPlistProperty(OSDictionary * dict, const OSString * key)
2372 {
2373 OSString * stringValue = NULL;// do not release
2374 const OSSymbol * symbolValue = NULL; // must release
2375
2376 stringValue = OSDynamicCast(OSString, dict->getObject(key));
2377 if (!stringValue) {
2378 goto finish;
2379 }
2380
2381 symbolValue = OSSymbol::withString(stringValue);
2382 if (!symbolValue) {
2383 goto finish;
2384 }
2385
2386 dict->setObject(key, symbolValue);
2387
2388 finish:
2389 if (symbolValue) {
2390 symbolValue->release();
2391 }
2392
2393 return;
2394 }
2395
2396 /*********************************************************************
2397 * Replace common personality property values with uniqued instances
2398 * to save on wired memory.
2399 *********************************************************************/
2400 /* static */
2401 void
2402 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict)
2403 {
2404 /* Properties every personality has.
2405 */
2406 uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKey);
2407 uniqueStringPlistProperty(personalityDict, kIOProviderClassKey);
2408 uniqueStringPlistProperty(personalityDict, gIOClassKey);
2409
2410 /* Other commonly used properties.
2411 */
2412 uniqueStringPlistProperty(personalityDict, gIOMatchCategoryKey);
2413 uniqueStringPlistProperty(personalityDict, gIOResourceMatchKey);
2414 uniqueStringPlistProperty(personalityDict, gIOUserClientClassKey);
2415
2416 uniqueStringPlistProperty(personalityDict, "HIDDefaultBehavior");
2417 uniqueStringPlistProperty(personalityDict, "HIDPointerAccelerationType");
2418 uniqueStringPlistProperty(personalityDict, "HIDRemoteControlType");
2419 uniqueStringPlistProperty(personalityDict, "HIDScrollAccelerationType");
2420 uniqueStringPlistProperty(personalityDict, "IOPersonalityPublisher");
2421 uniqueStringPlistProperty(personalityDict, "Physical Interconnect");
2422 uniqueStringPlistProperty(personalityDict, "Physical Interconnect Location");
2423 uniqueStringPlistProperty(personalityDict, "Vendor");
2424 uniqueStringPlistProperty(personalityDict, "Vendor Identification");
2425 uniqueStringPlistProperty(personalityDict, "Vendor Name");
2426 uniqueStringPlistProperty(personalityDict, "bConfigurationValue");
2427 uniqueStringPlistProperty(personalityDict, "bInterfaceNumber");
2428 uniqueStringPlistProperty(personalityDict, "idProduct");
2429
2430 return;
2431 }
2432
2433 /*********************************************************************
2434 *********************************************************************/
2435 void
2436 OSKext::free(void)
2437 {
2438 if (isLoaded()) {
2439 panic("Attempt to free loaded kext %s.", getIdentifierCString());
2440 }
2441
2442 OSSafeReleaseNULL(infoDict);
2443 OSSafeReleaseNULL(bundleID);
2444 OSSafeReleaseNULL(path);
2445 OSSafeReleaseNULL(executableRelPath);
2446 OSSafeReleaseNULL(dependencies);
2447 OSSafeReleaseNULL(linkedExecutable);
2448 OSSafeReleaseNULL(metaClasses);
2449 OSSafeReleaseNULL(interfaceUUID);
2450
2451 if (isInterface() && kmod_info) {
2452 kfree(kmod_info, sizeof(kmod_info_t));
2453 }
2454
2455 super::free();
2456 return;
2457 }
2458
2459 #if PRAGMA_MARK
2460 #pragma mark Mkext files
2461 #endif
2462 /*********************************************************************
2463 *********************************************************************/
2464 OSReturn
2465 OSKext::readMkextArchive(OSData * mkextData,
2466 uint32_t * checksumPtr)
2467 {
2468 OSReturn result = kOSKextReturnBadData;
2469 uint32_t mkextLength = 0;
2470 mkext_header * mkextHeader = 0;// do not free
2471 uint32_t mkextVersion = 0;
2472
2473 /* Note default return of kOSKextReturnBadData above.
2474 */
2475 mkextLength = mkextData->getLength();
2476 if (mkextLength < sizeof(mkext_basic_header)) {
2477 OSKextLog(/* kext */ NULL,
2478 kOSKextLogErrorLevel |
2479 kOSKextLogArchiveFlag,
2480 "Mkext archive too small to be valid.");
2481 goto finish;
2482 }
2483
2484 mkextHeader = (mkext_header *)mkextData->getBytesNoCopy();
2485
2486 if (MKEXT_GET_MAGIC(mkextHeader) != MKEXT_MAGIC ||
2487 MKEXT_GET_SIGNATURE(mkextHeader) != MKEXT_SIGN) {
2488 OSKextLog(/* kext */ NULL,
2489 kOSKextLogErrorLevel |
2490 kOSKextLogArchiveFlag,
2491 "Mkext archive has invalid magic or signature.");
2492 goto finish;
2493 }
2494
2495 if (MKEXT_GET_LENGTH(mkextHeader) != mkextLength) {
2496 OSKextLog(/* kext */ NULL,
2497 kOSKextLogErrorLevel |
2498 kOSKextLogArchiveFlag,
2499 "Mkext archive recorded length doesn't match actual file length.");
2500 goto finish;
2501 }
2502
2503 mkextVersion = MKEXT_GET_VERSION(mkextHeader);
2504
2505 if (mkextVersion == MKEXT_VERS_2) {
2506 result = OSKext::readMkext2Archive(mkextData, NULL, checksumPtr);
2507 } else {
2508 OSKextLog(/* kext */ NULL,
2509 kOSKextLogErrorLevel |
2510 kOSKextLogArchiveFlag,
2511 "Mkext archive of unsupported mkext version 0x%x.", mkextVersion);
2512 result = kOSKextReturnUnsupported;
2513 }
2514
2515 finish:
2516 return result;
2517 }
2518
2519 /*********************************************************************
2520 * Assumes magic, signature, version, length have been checked.
2521 * xxx - need to add further bounds checking for each file entry
2522 *
2523 * Should keep track of all kexts created so far, and if we hit a
2524 * fatal error halfway through, remove those kexts. If we've dropped
2525 * an older version that had already been read, whoops! Might want to
2526 * add a level of buffering?
2527 *********************************************************************/
2528 /* static */
2529 OSReturn
2530 OSKext::readMkext2Archive(
2531 OSData * mkextData,
2532 OSDictionary ** mkextPlistOut,
2533 uint32_t * checksumPtr)
2534 {
2535 OSReturn result = kOSReturnError;
2536 uint32_t mkextLength;
2537 mkext2_header * mkextHeader = NULL;// do not free
2538 void * mkextEnd = NULL;// do not free
2539 uint32_t mkextVersion;
2540 uint8_t * crc_address = NULL;
2541 uint32_t checksum;
2542 uint32_t mkextPlistOffset;
2543 uint32_t mkextPlistCompressedSize;
2544 char * mkextPlistEnd = NULL;// do not free
2545 uint32_t mkextPlistFullSize;
2546 OSString * errorString = NULL;// must release
2547 OSData * mkextPlistUncompressedData = NULL;// must release
2548 const char * mkextPlistDataBuffer = NULL;// do not free
2549 OSObject * parsedXML = NULL;// must release
2550 OSDictionary * mkextPlist = NULL;// do not release
2551 OSArray * mkextInfoDictArray = NULL;// do not release
2552 uint32_t count, i;
2553
2554 mkextLength = mkextData->getLength();
2555 mkextHeader = (mkext2_header *)mkextData->getBytesNoCopy();
2556 mkextEnd = (char *)mkextHeader + mkextLength;
2557 mkextVersion = MKEXT_GET_VERSION(mkextHeader);
2558
2559 crc_address = (u_int8_t *)&mkextHeader->version;
2560 checksum = mkext_adler32(crc_address,
2561 (uintptr_t)mkextHeader +
2562 MKEXT_GET_LENGTH(mkextHeader) - (uintptr_t)crc_address);
2563
2564 if (MKEXT_GET_CHECKSUM(mkextHeader) != checksum) {
2565 OSKextLog(/* kext */ NULL,
2566 kOSKextLogErrorLevel |
2567 kOSKextLogArchiveFlag,
2568 "Mkext archive has bad checksum.");
2569 result = kOSKextReturnBadData;
2570 goto finish;
2571 }
2572
2573 if (checksumPtr) {
2574 *checksumPtr = checksum;
2575 }
2576
2577 /* Check that the CPU type & subtype match that of the running kernel. */
2578 if (MKEXT_GET_CPUTYPE(mkextHeader) == (UInt32)CPU_TYPE_ANY) {
2579 OSKextLog(/* kext */ NULL,
2580 kOSKextLogErrorLevel |
2581 kOSKextLogArchiveFlag,
2582 "Mkext archive must have a specific CPU type.");
2583 result = kOSKextReturnBadData;
2584 goto finish;
2585 } else {
2586 if ((UInt32)_mh_execute_header.cputype !=
2587 MKEXT_GET_CPUTYPE(mkextHeader)) {
2588 OSKextLog(/* kext */ NULL,
2589 kOSKextLogErrorLevel |
2590 kOSKextLogArchiveFlag,
2591 "Mkext archive does not match the running kernel's CPU type.");
2592 result = kOSKextReturnArchNotFound;
2593 goto finish;
2594 }
2595 }
2596
2597 mkextPlistOffset = MKEXT2_GET_PLIST(mkextHeader);
2598 mkextPlistCompressedSize = MKEXT2_GET_PLIST_COMPSIZE(mkextHeader);
2599 mkextPlistEnd = (char *)mkextHeader + mkextPlistOffset +
2600 mkextPlistCompressedSize;
2601 if (mkextPlistEnd > mkextEnd) {
2602 OSKextLog(/* kext */ NULL,
2603 kOSKextLogErrorLevel |
2604 kOSKextLogArchiveFlag,
2605 "Mkext archive file overrun.");
2606 result = kOSKextReturnBadData;
2607 }
2608
2609 mkextPlistFullSize = MKEXT2_GET_PLIST_FULLSIZE(mkextHeader);
2610 if (mkextPlistCompressedSize) {
2611 mkextPlistUncompressedData = sKernelKext->extractMkext2FileData(
2612 (UInt8 *)mkextHeader + mkextPlistOffset,
2613 "plist",
2614 mkextPlistCompressedSize, mkextPlistFullSize);
2615 if (!mkextPlistUncompressedData) {
2616 goto finish;
2617 }
2618 mkextPlistDataBuffer = (const char *)
2619 mkextPlistUncompressedData->getBytesNoCopy();
2620 } else {
2621 mkextPlistDataBuffer = (const char *)mkextHeader + mkextPlistOffset;
2622 }
2623
2624 /* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
2625 */
2626 parsedXML = OSUnserializeXML(mkextPlistDataBuffer, &errorString);
2627 if (parsedXML) {
2628 mkextPlist = OSDynamicCast(OSDictionary, parsedXML);
2629 }
2630 if (!mkextPlist) {
2631 const char * errorCString = "(unknown error)";
2632
2633 if (errorString && errorString->getCStringNoCopy()) {
2634 errorCString = errorString->getCStringNoCopy();
2635 } else if (parsedXML) {
2636 errorCString = "not a dictionary";
2637 }
2638 OSKextLog(/* kext */ NULL,
2639 kOSKextLogErrorLevel |
2640 kOSKextLogArchiveFlag,
2641 "Error unserializing mkext plist: %s.", errorCString);
2642 goto finish;
2643 }
2644
2645 /* If the caller needs the plist, hand it back and retain it.
2646 * (This function releases it at the end.)
2647 */
2648 if (mkextPlistOut) {
2649 *mkextPlistOut = mkextPlist;
2650 (*mkextPlistOut)->retain();
2651 }
2652
2653 mkextInfoDictArray = OSDynamicCast(OSArray,
2654 mkextPlist->getObject(kMKEXTInfoDictionariesKey));
2655 if (!mkextInfoDictArray) {
2656 OSKextLog(/* kext */ NULL,
2657 kOSKextLogErrorLevel |
2658 kOSKextLogArchiveFlag,
2659 "Mkext archive contains no kext info dictionaries.");
2660 goto finish;
2661 }
2662
2663 count = mkextInfoDictArray->getCount();
2664 for (i = 0; i < count; i++) {
2665 OSDictionary * infoDict;
2666
2667
2668 infoDict = OSDynamicCast(OSDictionary,
2669 mkextInfoDictArray->getObject(i));
2670
2671 /* Create the kext for the entry, then release it, because the
2672 * kext system keeps them around until explicitly removed.
2673 * Any creation/registration failures are already logged for us.
2674 */
2675 if (infoDict) {
2676 OSKext * newKext = OSKext::withMkext2Info(infoDict, mkextData);
2677 OSSafeReleaseNULL(newKext);
2678 }
2679 }
2680
2681 /* Even if we didn't keep any kexts from the mkext, we may have a load
2682 * request to process, so we are successful (no errors occurred).
2683 */
2684 result = kOSReturnSuccess;
2685
2686 finish:
2687
2688 OSSafeReleaseNULL(parsedXML);
2689 OSSafeReleaseNULL(mkextPlistUncompressedData);
2690 OSSafeReleaseNULL(errorString);
2691
2692 return result;
2693 }
2694
2695 /*********************************************************************
2696 *********************************************************************/
2697 /* static */
2698 OSKext *
2699 OSKext::withMkext2Info(
2700 OSDictionary * anInfoDict,
2701 OSData * mkextData)
2702 {
2703 OSKext * newKext = new OSKext;
2704
2705 if (newKext && !newKext->initWithMkext2Info(anInfoDict, mkextData)) {
2706 newKext->release();
2707 return NULL;
2708 }
2709
2710 return newKext;
2711 }
2712
2713 /*********************************************************************
2714 *********************************************************************/
2715 bool
2716 OSKext::initWithMkext2Info(
2717 OSDictionary * anInfoDict,
2718 OSData * mkextData)
2719 {
2720 bool result = false;
2721 OSString * kextPath = NULL;// do not release
2722 OSNumber * executableOffsetNum = NULL;// do not release
2723 OSCollectionIterator * iterator = NULL;// must release
2724 OSData * executable = NULL;// must release
2725
2726 if (anInfoDict == NULL || !super::init()) {
2727 goto finish;
2728 }
2729
2730 /* Get the path. Don't look for an arch-specific path property.
2731 */
2732 kextPath = OSDynamicCast(OSString,
2733 anInfoDict->getObject(kMKEXTBundlePathKey));
2734
2735 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
2736 goto finish;
2737 }
2738
2739 /* If we have a path to the executable, save it.
2740 */
2741 executableRelPath = OSDynamicCast(OSString,
2742 anInfoDict->getObject(kMKEXTExecutableRelativePathKey));
2743 if (executableRelPath) {
2744 executableRelPath->retain();
2745 }
2746
2747 /* Don't need the paths to be in the info dictionary any more.
2748 */
2749 anInfoDict->removeObject(kMKEXTBundlePathKey);
2750 anInfoDict->removeObject(kMKEXTExecutableRelativePathKey);
2751
2752 executableOffsetNum = OSDynamicCast(OSNumber,
2753 infoDict->getObject(kMKEXTExecutableKey));
2754 if (executableOffsetNum) {
2755 executable = createMkext2FileEntry(mkextData,
2756 executableOffsetNum, "executable");
2757 infoDict->removeObject(kMKEXTExecutableKey);
2758 if (!executable) {
2759 goto finish;
2760 }
2761 if (!setExecutable(executable, mkextData, true)) {
2762 goto finish;
2763 }
2764 }
2765
2766 result = registerIdentifier();
2767
2768 finish:
2769
2770 OSSafeReleaseNULL(executable);
2771 OSSafeReleaseNULL(iterator);
2772 return result;
2773 }
2774
2775 /*********************************************************************
2776 *********************************************************************/
2777 OSData *
2778 OSKext::createMkext2FileEntry(
2779 OSData * mkextData,
2780 OSNumber * offsetNum,
2781 const char * name)
2782 {
2783 OSData * result = NULL;
2784 MkextEntryRef entryRef;
2785 uint8_t * mkextBuffer = (uint8_t *)mkextData->getBytesNoCopy();
2786 uint32_t entryOffset = offsetNum->unsigned32BitValue();
2787
2788 result = OSData::withCapacity(sizeof(entryRef));
2789 if (!result) {
2790 goto finish;
2791 }
2792
2793 entryRef.mkext = (mkext_basic_header *)mkextBuffer;
2794 entryRef.fileinfo = mkextBuffer + entryOffset;
2795 if (!result->appendBytes(&entryRef, sizeof(entryRef))) {
2796 OSSafeReleaseNULL(result);
2797 goto finish;
2798 }
2799
2800 finish:
2801 if (!result) {
2802 OSKextLog(this,
2803 kOSKextLogErrorLevel |
2804 kOSKextLogArchiveFlag,
2805 "Can't create wrapper for mkext file entry '%s' of kext %s.",
2806 name, getIdentifierCString());
2807 }
2808 return result;
2809 }
2810
2811 /*********************************************************************
2812 *********************************************************************/
2813 extern "C" {
2814 static void * z_alloc(void *, u_int items, u_int size);
2815 static void z_free(void *, void *ptr);
2816
2817 typedef struct z_mem {
2818 uint32_t alloc_size;
2819 uint8_t data[0];
2820 } z_mem;
2821
2822 /*
2823 * Space allocation and freeing routines for use by zlib routines.
2824 */
2825 void *
2826 z_alloc(void * notused __unused, u_int num_items, u_int size)
2827 {
2828 void * result = NULL;
2829 z_mem * zmem = NULL;
2830
2831 uint64_t total = ((uint64_t)num_items) * ((uint64_t)size);
2832 //Check for overflow due to multiplication
2833 if (total > UINT32_MAX) {
2834 panic("z_alloc(%p, %x, %x): overflow caused by %x * %x\n",
2835 notused, num_items, size, num_items, size);
2836 }
2837
2838 uint64_t allocSize64 = total + ((uint64_t)sizeof(zmem));
2839 //Check for overflow due to addition
2840 if (allocSize64 > UINT32_MAX) {
2841 panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx\n",
2842 notused, num_items, size, (uint32_t)total, sizeof(zmem));
2843 }
2844 uint32_t allocSize = (uint32_t)allocSize64;
2845
2846 zmem = (z_mem *)kalloc_tag(allocSize, VM_KERN_MEMORY_OSKEXT);
2847 if (!zmem) {
2848 goto finish;
2849 }
2850 zmem->alloc_size = allocSize;
2851 result = (void *)&(zmem->data);
2852 finish:
2853 return result;
2854 }
2855
2856 void
2857 z_free(void * notused __unused, void * ptr)
2858 {
2859 uint32_t * skipper = (uint32_t *)ptr - 1;
2860 z_mem * zmem = (z_mem *)skipper;
2861 kfree(zmem, zmem->alloc_size);
2862 return;
2863 }
2864 };
2865
2866 OSData *
2867 OSKext::extractMkext2FileData(
2868 UInt8 * data,
2869 const char * name,
2870 uint32_t compressedSize,
2871 uint32_t fullSize)
2872 {
2873 OSData * result = NULL;
2874
2875 OSData * uncompressedData = NULL;// release on error
2876
2877 uint8_t * uncompressedDataBuffer = 0;// do not free
2878 unsigned long uncompressedSize;
2879 z_stream zstream;
2880 bool zstream_inited = false;
2881 int zlib_result;
2882
2883 /* If the file isn't compressed, we want to make a copy
2884 * so that we don't have the tie to the larger mkext file buffer any more.
2885 */
2886 if (!compressedSize) {
2887 uncompressedData = OSData::withBytes(data, fullSize);
2888 // xxx - no check for failure?
2889 result = uncompressedData;
2890 goto finish;
2891 }
2892
2893 if (KERN_SUCCESS != kmem_alloc(kernel_map,
2894 (vm_offset_t*)&uncompressedDataBuffer, fullSize, VM_KERN_MEMORY_OSKEXT)) {
2895 /* How's this for cheesy? The kernel is only asked to extract
2896 * kext plists so we tailor the log messages.
2897 */
2898 if (isKernel()) {
2899 OSKextLog(this,
2900 kOSKextLogErrorLevel |
2901 kOSKextLogArchiveFlag,
2902 "Allocation failure extracting %s from mkext.", name);
2903 } else {
2904 OSKextLog(this,
2905 kOSKextLogErrorLevel |
2906 kOSKextLogArchiveFlag,
2907 "Allocation failure extracting %s from mkext for kext %s.",
2908 name, getIdentifierCString());
2909 }
2910
2911 goto finish;
2912 }
2913 uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer, fullSize);
2914 if (!uncompressedData) {
2915 if (isKernel()) {
2916 OSKextLog(this,
2917 kOSKextLogErrorLevel |
2918 kOSKextLogArchiveFlag,
2919 "Allocation failure extracting %s from mkext.", name);
2920 } else {
2921 OSKextLog(this,
2922 kOSKextLogErrorLevel |
2923 kOSKextLogArchiveFlag,
2924 "Allocation failure extracting %s from mkext for kext %s.",
2925 name, getIdentifierCString());
2926 }
2927 goto finish;
2928 }
2929 uncompressedData->setDeallocFunction(&osdata_kmem_free);
2930
2931 if (isKernel()) {
2932 OSKextLog(this,
2933 kOSKextLogDetailLevel |
2934 kOSKextLogArchiveFlag,
2935 "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
2936 name, compressedSize, fullSize);
2937 } else {
2938 OSKextLog(this,
2939 kOSKextLogDetailLevel |
2940 kOSKextLogArchiveFlag,
2941 "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
2942 getIdentifierCString(), name, compressedSize, fullSize);
2943 }
2944
2945 bzero(&zstream, sizeof(zstream));
2946 zstream.next_in = (UInt8 *)data;
2947 zstream.avail_in = compressedSize;
2948
2949 zstream.next_out = uncompressedDataBuffer;
2950 zstream.avail_out = fullSize;
2951
2952 zstream.zalloc = z_alloc;
2953 zstream.zfree = z_free;
2954
2955 zlib_result = inflateInit(&zstream);
2956 if (Z_OK != zlib_result) {
2957 if (isKernel()) {
2958 OSKextLog(this,
2959 kOSKextLogErrorLevel |
2960 kOSKextLogArchiveFlag,
2961 "Mkext error; zlib inflateInit failed (%d) for %s.",
2962 zlib_result, name);
2963 } else {
2964 OSKextLog(this,
2965 kOSKextLogErrorLevel |
2966 kOSKextLogArchiveFlag,
2967 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
2968 getIdentifierCString(), zlib_result, name);
2969 }
2970 goto finish;
2971 } else {
2972 zstream_inited = true;
2973 }
2974
2975 zlib_result = inflate(&zstream, Z_FINISH);
2976
2977 if (zlib_result == Z_STREAM_END || zlib_result == Z_OK) {
2978 uncompressedSize = zstream.total_out;
2979 } else {
2980 if (isKernel()) {
2981 OSKextLog(this,
2982 kOSKextLogErrorLevel |
2983 kOSKextLogArchiveFlag,
2984 "Mkext error; zlib inflate failed (%d) for %s.",
2985 zlib_result, name);
2986 } else {
2987 OSKextLog(this,
2988 kOSKextLogErrorLevel |
2989 kOSKextLogArchiveFlag,
2990 "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
2991 getIdentifierCString(), zlib_result, name);
2992 }
2993 if (zstream.msg) {
2994 OSKextLog(this,
2995 kOSKextLogErrorLevel |
2996 kOSKextLogArchiveFlag,
2997 "zlib error: %s.", zstream.msg);
2998 }
2999 goto finish;
3000 }
3001
3002 if (uncompressedSize != fullSize) {
3003 if (isKernel()) {
3004 OSKextLog(this,
3005 kOSKextLogErrorLevel |
3006 kOSKextLogArchiveFlag,
3007 "Mkext error; zlib inflate discrepancy for %s, "
3008 "uncompressed size != original size.", name);
3009 } else {
3010 OSKextLog(this,
3011 kOSKextLogErrorLevel |
3012 kOSKextLogArchiveFlag,
3013 "Kext %s - mkext error; zlib inflate discrepancy for %s, "
3014 "uncompressed size != original size.",
3015 getIdentifierCString(), name);
3016 }
3017 goto finish;
3018 }
3019
3020 result = uncompressedData;
3021
3022 finish:
3023 /* Don't bother checking return, nothing we can do on fail.
3024 */
3025 if (zstream_inited) {
3026 inflateEnd(&zstream);
3027 }
3028
3029 if (!result) {
3030 OSSafeReleaseNULL(uncompressedData);
3031 }
3032
3033 return result;
3034 }
3035
3036 /*********************************************************************
3037 *********************************************************************/
3038 /* static */
3039 OSReturn
3040 OSKext::loadFromMkext(
3041 OSKextLogSpec clientLogFilter,
3042 char * mkextBuffer,
3043 uint32_t mkextBufferLength,
3044 char ** logInfoOut,
3045 uint32_t * logInfoLengthOut)
3046 {
3047 OSReturn result = kOSReturnError;
3048 OSReturn tempResult = kOSReturnError;
3049
3050 OSData * mkextData = NULL;// must release
3051 OSDictionary * mkextPlist = NULL;// must release
3052
3053 OSArray * logInfoArray = NULL;// must release
3054 OSSerialize * serializer = NULL;// must release
3055
3056 OSString * predicate = NULL;// do not release
3057 OSDictionary * requestArgs = NULL;// do not release
3058
3059 OSString * kextIdentifier = NULL;// do not release
3060 OSNumber * startKextExcludeNum = NULL;// do not release
3061 OSNumber * startMatchingExcludeNum = NULL;// do not release
3062 OSBoolean * delayAutounloadBool = NULL;// do not release
3063 OSArray * personalityNames = NULL;// do not release
3064
3065 /* Default values for these two options: regular autounload behavior,
3066 * load all kexts, send no personalities.
3067 */
3068 Boolean delayAutounload = false;
3069 OSKextExcludeLevel startKextExcludeLevel = kOSKextExcludeNone;
3070 OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeAll;
3071
3072 IORecursiveLockLock(sKextLock);
3073
3074 if (logInfoOut) {
3075 *logInfoOut = NULL;
3076 *logInfoLengthOut = 0;
3077 }
3078
3079 OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
3080
3081 OSKextLog(/* kext */ NULL,
3082 kOSKextLogDebugLevel |
3083 kOSKextLogIPCFlag,
3084 "Received kext load request from user space.");
3085
3086 /* Regardless of processing, the fact that we have gotten here means some
3087 * user-space program is up and talking to us, so we'll switch our kext
3088 * registration to reflect that.
3089 */
3090 if (!sUserLoadsActive) {
3091 OSKextLog(/* kext */ NULL,
3092 kOSKextLogProgressLevel |
3093 kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
3094 "Switching to late startup (user-space) kext loading policy.");
3095
3096 sUserLoadsActive = true;
3097 }
3098
3099 if (!sLoadEnabled) {
3100 OSKextLog(/* kext */ NULL,
3101 kOSKextLogErrorLevel |
3102 kOSKextLogLoadFlag,
3103 "Kext loading is disabled.");
3104 result = kOSKextReturnDisabled;
3105 goto finish;
3106 }
3107
3108 /* Note that we do not set a dealloc function on this OSData
3109 * object! No references to it can remain after the loadFromMkext()
3110 * call since we are in a MIG function, and will vm_deallocate()
3111 * the buffer.
3112 */
3113 mkextData = OSData::withBytesNoCopy(mkextBuffer,
3114 mkextBufferLength);
3115 if (!mkextData) {
3116 OSKextLog(/* kext */ NULL,
3117 kOSKextLogErrorLevel |
3118 kOSKextLogLoadFlag | kOSKextLogIPCFlag,
3119 "Failed to create wrapper for kext load request.");
3120 result = kOSKextReturnNoMemory;
3121 goto finish;
3122 }
3123
3124 result = readMkext2Archive(mkextData, &mkextPlist, NULL);
3125 if (result != kOSReturnSuccess) {
3126 OSKextLog(/* kext */ NULL,
3127 kOSKextLogErrorLevel |
3128 kOSKextLogLoadFlag,
3129 "Failed to read kext load request.");
3130 goto finish;
3131 }
3132
3133 predicate = _OSKextGetRequestPredicate(mkextPlist);
3134 if (!predicate || !predicate->isEqualTo(kKextRequestPredicateLoad)) {
3135 OSKextLog(/* kext */ NULL,
3136 kOSKextLogErrorLevel |
3137 kOSKextLogLoadFlag,
3138 "Received kext load request with no predicate; skipping.");
3139 result = kOSKextReturnInvalidArgument;
3140 goto finish;
3141 }
3142
3143 requestArgs = OSDynamicCast(OSDictionary,
3144 mkextPlist->getObject(kKextRequestArgumentsKey));
3145 if (!requestArgs || !requestArgs->getCount()) {
3146 OSKextLog(/* kext */ NULL,
3147 kOSKextLogErrorLevel |
3148 kOSKextLogLoadFlag,
3149 "Received kext load request with no arguments.");
3150 result = kOSKextReturnInvalidArgument;
3151 goto finish;
3152 }
3153
3154 kextIdentifier = OSDynamicCast(OSString,
3155 requestArgs->getObject(kKextRequestArgumentBundleIdentifierKey));
3156 if (!kextIdentifier) {
3157 OSKextLog(/* kext */ NULL,
3158 kOSKextLogErrorLevel |
3159 kOSKextLogLoadFlag,
3160 "Received kext load request with no kext identifier.");
3161 result = kOSKextReturnInvalidArgument;
3162 goto finish;
3163 }
3164
3165 startKextExcludeNum = OSDynamicCast(OSNumber,
3166 requestArgs->getObject(kKextRequestArgumentStartExcludeKey));
3167 startMatchingExcludeNum = OSDynamicCast(OSNumber,
3168 requestArgs->getObject(kKextRequestArgumentStartMatchingExcludeKey));
3169 delayAutounloadBool = OSDynamicCast(OSBoolean,
3170 requestArgs->getObject(kKextRequestArgumentDelayAutounloadKey));
3171 personalityNames = OSDynamicCast(OSArray,
3172 requestArgs->getObject(kKextRequestArgumentPersonalityNamesKey));
3173
3174 if (delayAutounloadBool) {
3175 delayAutounload = delayAutounloadBool->getValue();
3176 }
3177 if (startKextExcludeNum) {
3178 startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
3179 }
3180 if (startMatchingExcludeNum) {
3181 startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
3182 }
3183
3184 OSKextLog(/* kext */ NULL,
3185 kOSKextLogProgressLevel |
3186 kOSKextLogIPCFlag,
3187 "Received request from user space to load kext %s.",
3188 kextIdentifier->getCStringNoCopy());
3189
3190 /* Load the kext, with no deferral, since this is a load from outside
3191 * the kernel.
3192 * xxx - Would like a better way to handle the default values for the
3193 * xxx - start/match opt args.
3194 */
3195 result = OSKext::loadKextWithIdentifier(
3196 kextIdentifier,
3197 /* allowDefer */ false,
3198 delayAutounload,
3199 startKextExcludeLevel,
3200 startMatchingExcludeLevel,
3201 personalityNames);
3202 if (result != kOSReturnSuccess) {
3203 goto finish;
3204 }
3205 /* If the load came down from kextd, it will shortly inform IOCatalogue
3206 * for matching via a separate IOKit calldown.
3207 */
3208
3209 finish:
3210
3211 /* Gather up the collected log messages for user space. Any
3212 * error messages past this call will not make it up as log messages
3213 * but will be in the system log.
3214 */
3215 logInfoArray = OSKext::clearUserSpaceLogFilter();
3216
3217 if (logInfoArray && logInfoOut && logInfoLengthOut) {
3218 tempResult = OSKext::serializeLogInfo(logInfoArray,
3219 logInfoOut, logInfoLengthOut);
3220 if (tempResult != kOSReturnSuccess) {
3221 result = tempResult;
3222 }
3223 }
3224
3225 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
3226
3227 /* Note: mkextDataObject will have been retained by every kext w/an
3228 * executable in it. That should all have been flushed out at the
3229 * and of the load operation, but you never know....
3230 */
3231 if (mkextData && mkextData->getRetainCount() > 1) {
3232 OSKextLog(/* kext */ NULL,
3233 kOSKextLogErrorLevel |
3234 kOSKextLogLoadFlag | kOSKextLogIPCFlag,
3235 "Kext load request buffer from user space still retained by a kext; "
3236 "probable memory leak.");
3237 }
3238
3239 IORecursiveLockUnlock(sKextLock);
3240
3241 OSSafeReleaseNULL(mkextData);
3242 OSSafeReleaseNULL(mkextPlist);
3243 OSSafeReleaseNULL(serializer);
3244 OSSafeReleaseNULL(logInfoArray);
3245
3246 return result;
3247 }
3248
3249 /*********************************************************************
3250 *********************************************************************/
3251 /* static */
3252 OSReturn
3253 OSKext::serializeLogInfo(
3254 OSArray * logInfoArray,
3255 char ** logInfoOut,
3256 uint32_t * logInfoLengthOut)
3257 {
3258 OSReturn result = kOSReturnError;
3259 char * buffer = NULL;
3260 kern_return_t kmem_result = KERN_FAILURE;
3261 OSSerialize * serializer = NULL;// must release; reused
3262 char * logInfo = NULL;// returned by reference
3263 uint32_t logInfoLength = 0;
3264
3265 if (!logInfoArray || !logInfoOut || !logInfoLengthOut) {
3266 OSKextLog(/* kext */ NULL,
3267 kOSKextLogErrorLevel |
3268 kOSKextLogIPCFlag,
3269 "Internal error; invalid arguments to OSKext::serializeLogInfo().");
3270 /* Bad programmer. */
3271 result = kOSKextReturnInvalidArgument;
3272 goto finish;
3273 }
3274
3275 serializer = OSSerialize::withCapacity(0);
3276 if (!serializer) {
3277 OSKextLog(/* kext */ NULL,
3278 kOSKextLogErrorLevel |
3279 kOSKextLogIPCFlag,
3280 "Failed to create serializer on log info for request from user space.");
3281 /* Incidental error; we're going to (try to) allow the request
3282 * itself to succeed. */
3283 }
3284
3285 if (!logInfoArray->serialize(serializer)) {
3286 OSKextLog(/* kext */ NULL,
3287 kOSKextLogErrorLevel |
3288 kOSKextLogIPCFlag,
3289 "Failed to serialize log info for request from user space.");
3290 /* Incidental error; we're going to (try to) allow the request
3291 * itself to succeed. */
3292 } else {
3293 logInfo = serializer->text();
3294 logInfoLength = serializer->getLength();
3295
3296 kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, round_page(logInfoLength), VM_KERN_MEMORY_OSKEXT);
3297 if (kmem_result != KERN_SUCCESS) {
3298 OSKextLog(/* kext */ NULL,
3299 kOSKextLogErrorLevel |
3300 kOSKextLogIPCFlag,
3301 "Failed to copy log info for request from user space.");
3302 /* Incidental error; we're going to (try to) allow the request
3303 * to succeed. */
3304 } else {
3305 /* 11981737 - clear uninitialized data in last page */
3306 bzero((void *)(buffer + logInfoLength),
3307 (round_page(logInfoLength) - logInfoLength));
3308 memcpy(buffer, logInfo, logInfoLength);
3309 *logInfoOut = buffer;
3310 *logInfoLengthOut = logInfoLength;
3311 }
3312 }
3313
3314 result = kOSReturnSuccess;
3315 finish:
3316 OSSafeReleaseNULL(serializer);
3317 return result;
3318 }
3319
3320 #if PRAGMA_MARK
3321 #pragma mark Instance Management Methods
3322 #endif
3323 /*********************************************************************
3324 *********************************************************************/
3325 OSKext *
3326 OSKext::lookupKextWithIdentifier(const char * kextIdentifier)
3327 {
3328 OSKext * foundKext = NULL;
3329
3330 IORecursiveLockLock(sKextLock);
3331 foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
3332 if (foundKext) {
3333 foundKext->retain();
3334 }
3335 IORecursiveLockUnlock(sKextLock);
3336
3337 return foundKext;
3338 }
3339
3340 /*********************************************************************
3341 *********************************************************************/
3342 OSKext *
3343 OSKext::lookupKextWithIdentifier(OSString * kextIdentifier)
3344 {
3345 return OSKext::lookupKextWithIdentifier(kextIdentifier->getCStringNoCopy());
3346 }
3347
3348 /*********************************************************************
3349 *********************************************************************/
3350 OSKext *
3351 OSKext::lookupKextWithLoadTag(uint32_t aTag)
3352 {
3353 OSKext * foundKext = NULL; // returned
3354 uint32_t count, i;
3355
3356 IORecursiveLockLock(sKextLock);
3357
3358 count = sLoadedKexts->getCount();
3359 for (i = 0; i < count; i++) {
3360 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
3361 if (thisKext->getLoadTag() == aTag) {
3362 foundKext = thisKext;
3363 foundKext->retain();
3364 goto finish;
3365 }
3366 }
3367
3368 finish:
3369 IORecursiveLockUnlock(sKextLock);
3370
3371 return foundKext;
3372 }
3373
3374 /*********************************************************************
3375 *********************************************************************/
3376 OSKext *
3377 OSKext::lookupKextWithAddress(vm_address_t address)
3378 {
3379 OSKext * foundKext = NULL; // returned
3380 uint32_t count, i;
3381
3382 IORecursiveLockLock(sKextLock);
3383
3384 count = sLoadedKexts->getCount();
3385 for (i = 0; i < count; i++) {
3386 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
3387 if (thisKext->linkedExecutable) {
3388 vm_address_t kext_start =
3389 (vm_address_t)thisKext->linkedExecutable->getBytesNoCopy();
3390 vm_address_t kext_end = kext_start +
3391 thisKext->linkedExecutable->getLength();
3392 if ((kext_start <= address) && (address < kext_end)) {
3393 foundKext = thisKext;
3394 foundKext->retain();
3395 goto finish;
3396 }
3397 }
3398 }
3399
3400 finish:
3401 IORecursiveLockUnlock(sKextLock);
3402
3403 return foundKext;
3404 }
3405
3406 OSData *
3407 OSKext::copyKextUUIDForAddress(OSNumber *address)
3408 {
3409 OSData * uuid = NULL;
3410 OSKextActiveAccount * active;
3411 OSKext * kext = NULL;
3412 uint32_t baseIdx;
3413 uint32_t lim;
3414
3415 if (!address) {
3416 return NULL;
3417 }
3418
3419 uintptr_t addr = ml_static_slide((uintptr_t)address->unsigned64BitValue());
3420
3421 #if CONFIG_MACF
3422 /* Is the calling process allowed to query kext info? */
3423 if (current_task() != kernel_task) {
3424 int macCheckResult = 0;
3425 kauth_cred_t cred = NULL;
3426
3427 cred = kauth_cred_get_with_ref();
3428 macCheckResult = mac_kext_check_query(cred);
3429 kauth_cred_unref(&cred);
3430
3431 if (macCheckResult != 0) {
3432 OSKextLog(/* kext */ NULL,
3433 kOSKextLogErrorLevel | kOSKextLogLoadFlag,
3434 "Failed to query kext UUID (MAC policy error 0x%x).",
3435 macCheckResult);
3436 return NULL;
3437 }
3438 }
3439 #endif
3440
3441 IOSimpleLockLock(sKextAccountsLock);
3442 // bsearch sKextAccounts list
3443 for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
3444 active = &sKextAccounts[baseIdx + (lim >> 1)];
3445 if ((addr >= active->address) && (addr < active->address_end)) {
3446 kext = active->account->kext;
3447 if (kext) {
3448 kext->retain();
3449 }
3450 break;
3451 } else if (addr > active->address) {
3452 // move right
3453 baseIdx += (lim >> 1) + 1;
3454 lim--;
3455 }
3456 // else move left
3457 }
3458 IOSimpleLockUnlock(sKextAccountsLock);
3459
3460 if (kext) {
3461 uuid = kext->copyTextUUID();
3462 kext->release();
3463 } else if (((vm_offset_t)addr >= vm_kernel_stext) && ((vm_offset_t)addr < vm_kernel_etext)) {
3464 uuid = sKernelKext->copyTextUUID();
3465 }
3466
3467 return uuid;
3468 }
3469
3470 /*********************************************************************
3471 *********************************************************************/
3472 OSKext *
3473 OSKext::lookupKextWithUUID(uuid_t wanted)
3474 {
3475 OSKext * foundKext = NULL; // returned
3476 uint32_t count, i;
3477
3478 IORecursiveLockLock(sKextLock);
3479
3480 count = sLoadedKexts->getCount();
3481
3482 for (i = 0; i < count; i++) {
3483 OSKext * thisKext = NULL;
3484
3485 thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
3486 if (!thisKext) {
3487 continue;
3488 }
3489
3490 OSData *uuid_data = thisKext->copyUUID();
3491 if (!uuid_data) {
3492 continue;
3493 }
3494
3495 uuid_t uuid;
3496 memcpy(&uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
3497 uuid_data->release();
3498
3499 if (0 == uuid_compare(wanted, uuid)) {
3500 foundKext = thisKext;
3501 foundKext->retain();
3502 goto finish;
3503 }
3504 }
3505
3506 finish:
3507 IORecursiveLockUnlock(sKextLock);
3508
3509 return foundKext;
3510 }
3511
3512
3513
3514
3515 /*********************************************************************
3516 *********************************************************************/
3517 /* static */
3518 bool
3519 OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier)
3520 {
3521 bool result = false;
3522 OSKext * foundKext = NULL; // returned
3523
3524 IORecursiveLockLock(sKextLock);
3525
3526 foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
3527 if (foundKext && foundKext->isLoaded()) {
3528 result = true;
3529 }
3530
3531 IORecursiveLockUnlock(sKextLock);
3532
3533 return result;
3534 }
3535
3536 /*********************************************************************
3537 * xxx - should spawn a separate thread so a kext can safely have
3538 * xxx - itself unloaded.
3539 *********************************************************************/
3540 /* static */
3541 OSReturn
3542 OSKext::removeKext(
3543 OSKext * aKext,
3544 #if CONFIG_EMBEDDED
3545 __unused
3546 #endif
3547 bool terminateServicesAndRemovePersonalitiesFlag)
3548 {
3549 #if CONFIG_EMBEDDED
3550 OSKextLog(aKext,
3551 kOSKextLogErrorLevel |
3552 kOSKextLogKextBookkeepingFlag,
3553 "removeKext() called for %s, not supported on embedded",
3554 aKext->getIdentifier() ? aKext->getIdentifierCString() : "unknown kext");
3555
3556 return kOSReturnSuccess;
3557 #else /* CONFIG_EMBEDDED */
3558
3559 OSReturn result = kOSKextReturnInUse;
3560 OSKext * checkKext = NULL; // do not release
3561 #if CONFIG_MACF
3562 int macCheckResult = 0;
3563 kauth_cred_t cred = NULL;
3564 #endif
3565
3566 IORecursiveLockLock(sKextLock);
3567
3568 /* If the kext has no identifier, it failed to init
3569 * so isn't in sKextsByID and it isn't loaded.
3570 */
3571 if (!aKext->getIdentifier()) {
3572 result = kOSReturnSuccess;
3573 goto finish;
3574 }
3575
3576 checkKext = OSDynamicCast(OSKext,
3577 sKextsByID->getObject(aKext->getIdentifier()));
3578 if (checkKext != aKext) {
3579 result = kOSKextReturnNotFound;
3580 goto finish;
3581 }
3582
3583 if (aKext->isLoaded()) {
3584 #if CONFIG_MACF
3585 if (current_task() != kernel_task) {
3586 cred = kauth_cred_get_with_ref();
3587 macCheckResult = mac_kext_check_unload(cred, aKext->getIdentifierCString());
3588 kauth_cred_unref(&cred);
3589 }
3590
3591 if (macCheckResult != 0) {
3592 result = kOSReturnError;
3593 OSKextLog(aKext,
3594 kOSKextLogErrorLevel |
3595 kOSKextLogKextBookkeepingFlag,
3596 "Failed to remove kext %s (MAC policy error 0x%x).",
3597 aKext->getIdentifierCString(), macCheckResult);
3598 goto finish;
3599 }
3600 #endif
3601
3602 /* make sure there are no resource requests in flight - 17187548 */
3603 if (aKext->countRequestCallbacks()) {
3604 goto finish;
3605 }
3606
3607 /* If we are terminating, send the request to the IOCatalogue
3608 * (which will actually call us right back but that's ok we have
3609 * a recursive lock don't you know) but do not ask the IOCatalogue
3610 * to call back with an unload, we'll do that right here.
3611 */
3612 if (terminateServicesAndRemovePersonalitiesFlag) {
3613 result = gIOCatalogue->terminateDriversForModule(
3614 aKext->getIdentifierCString(), /* unload */ false);
3615 if (result != kOSReturnSuccess) {
3616 OSKextLog(aKext,
3617 kOSKextLogErrorLevel |
3618 kOSKextLogKextBookkeepingFlag,
3619 "Can't remove kext %s; services failed to terminate - 0x%x.",
3620 aKext->getIdentifierCString(), result);
3621 goto finish;
3622 }
3623 }
3624
3625 result = aKext->unload();
3626 if (result != kOSReturnSuccess) {
3627 goto finish;
3628 }
3629 }
3630
3631 /* Remove personalities as requested. This is a bit redundant for a loaded
3632 * kext as IOCatalogue::terminateDriversForModule() removes driver
3633 * personalities, but it doesn't restart matching, which we always want
3634 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
3635 * that happens.
3636 */
3637 if (terminateServicesAndRemovePersonalitiesFlag) {
3638 aKext->removePersonalitiesFromCatalog();
3639 }
3640
3641 OSKextLog(aKext,
3642 kOSKextLogProgressLevel |
3643 kOSKextLogKextBookkeepingFlag,
3644 "Removing kext %s.",
3645 aKext->getIdentifierCString());
3646
3647 sKextsByID->removeObject(aKext->getIdentifier());
3648 result = kOSReturnSuccess;
3649
3650 finish:
3651 IORecursiveLockUnlock(sKextLock);
3652 return result;
3653 #endif /* CONFIG_EMBEDDED */
3654 }
3655
3656 /*********************************************************************
3657 *********************************************************************/
3658 /* static */
3659 OSReturn
3660 OSKext::removeKextWithIdentifier(
3661 const char * kextIdentifier,
3662 bool terminateServicesAndRemovePersonalitiesFlag)
3663 {
3664 OSReturn result = kOSReturnError;
3665
3666 IORecursiveLockLock(sKextLock);
3667
3668 OSKext * aKext = OSDynamicCast(OSKext,
3669 sKextsByID->getObject(kextIdentifier));
3670 if (!aKext) {
3671 result = kOSKextReturnNotFound;
3672 OSKextLog(/* kext */ NULL,
3673 kOSKextLogErrorLevel |
3674 kOSKextLogKextBookkeepingFlag,
3675 "Can't remove kext %s - not found.",
3676 kextIdentifier);
3677 goto finish;
3678 }
3679
3680 result = OSKext::removeKext(aKext,
3681 terminateServicesAndRemovePersonalitiesFlag);
3682
3683 finish:
3684 IORecursiveLockUnlock(sKextLock);
3685
3686 return result;
3687 }
3688
3689 /*********************************************************************
3690 *********************************************************************/
3691 /* static */
3692 OSReturn
3693 OSKext::removeKextWithLoadTag(
3694 OSKextLoadTag loadTag,
3695 bool terminateServicesAndRemovePersonalitiesFlag)
3696 {
3697 OSReturn result = kOSReturnError;
3698 OSKext * foundKext = NULL;
3699 uint32_t count, i;
3700
3701 IORecursiveLockLock(sKextLock);
3702
3703 count = sLoadedKexts->getCount();
3704 for (i = 0; i < count; i++) {
3705 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
3706 if (thisKext->loadTag == loadTag) {
3707 foundKext = thisKext;
3708 break;
3709 }
3710 }
3711
3712 if (!foundKext) {
3713 result = kOSKextReturnNotFound;
3714 OSKextLog(/* kext */ NULL,
3715 kOSKextLogErrorLevel |
3716 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
3717 "Can't remove kext with load tag %d - not found.",
3718 loadTag);
3719 goto finish;
3720 }
3721
3722 result = OSKext::removeKext(foundKext,
3723 terminateServicesAndRemovePersonalitiesFlag);
3724
3725 finish:
3726 IORecursiveLockUnlock(sKextLock);
3727
3728 return result;
3729 }
3730
3731 /*********************************************************************
3732 *********************************************************************/
3733 OSDictionary *
3734 OSKext::copyKexts(void)
3735 {
3736 OSDictionary * result;
3737
3738 IORecursiveLockLock(sKextLock);
3739 result = OSDynamicCast(OSDictionary, sKextsByID->copyCollection());
3740 IORecursiveLockUnlock(sKextLock);
3741
3742 return result;
3743 }
3744
3745 /*********************************************************************
3746 *********************************************************************/
3747 #define BOOTER_KEXT_PREFIX "Driver-"
3748
3749 typedef struct _DeviceTreeBuffer {
3750 uint32_t paddr;
3751 uint32_t length;
3752 } _DeviceTreeBuffer;
3753
3754 /*********************************************************************
3755 * Create a dictionary of excluded kexts from the given booter data.
3756 *********************************************************************/
3757 /* static */
3758 void
3759 OSKext::createExcludeListFromBooterData(
3760 OSDictionary * theDictionary,
3761 OSCollectionIterator * theIterator )
3762 {
3763 OSString * deviceTreeName = NULL;// do not release
3764 const _DeviceTreeBuffer * deviceTreeBuffer = NULL;// do not release
3765 char * booterDataPtr = NULL;// do not release
3766 _BooterKextFileInfo * kextFileInfo = NULL;// do not release
3767 char * infoDictAddr = NULL;// do not release
3768 OSObject * parsedXML = NULL;// must release
3769 OSDictionary * theInfoDict = NULL;// do not release
3770
3771 theIterator->reset();
3772
3773 /* look for AppleKextExcludeList.kext */
3774 while ((deviceTreeName =
3775 OSDynamicCast(OSString, theIterator->getNextObject()))) {
3776 const char * devTreeNameCString;
3777 OSData * deviceTreeEntry;
3778 OSString * myBundleID;// do not release
3779
3780 OSSafeReleaseNULL(parsedXML);
3781
3782 deviceTreeEntry =
3783 OSDynamicCast(OSData, theDictionary->getObject(deviceTreeName));
3784 if (!deviceTreeEntry) {
3785 continue;
3786 }
3787
3788 /* Make sure it is a kext */
3789 devTreeNameCString = deviceTreeName->getCStringNoCopy();
3790 if (strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX,
3791 (sizeof(BOOTER_KEXT_PREFIX) - 1)) != 0) {
3792 OSKextLog(NULL,
3793 kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
3794 "\"%s\" not a kext",
3795 devTreeNameCString);
3796 continue;
3797 }
3798
3799 deviceTreeBuffer = (const _DeviceTreeBuffer *)
3800 deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer));
3801 if (!deviceTreeBuffer) {
3802 continue;
3803 }
3804
3805 booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr);
3806 if (!booterDataPtr) {
3807 continue;
3808 }
3809
3810 kextFileInfo = (_BooterKextFileInfo *) booterDataPtr;
3811 if (!kextFileInfo->infoDictPhysAddr ||
3812 !kextFileInfo->infoDictLength) {
3813 continue;
3814 }
3815
3816 infoDictAddr = (char *)
3817 ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
3818 if (!infoDictAddr) {
3819 continue;
3820 }
3821
3822 parsedXML = OSUnserializeXML(infoDictAddr);
3823 if (!parsedXML) {
3824 continue;
3825 }
3826
3827 theInfoDict = OSDynamicCast(OSDictionary, parsedXML);
3828 if (!theInfoDict) {
3829 continue;
3830 }
3831
3832 myBundleID =
3833 OSDynamicCast(OSString,
3834 theInfoDict->getObject(kCFBundleIdentifierKey));
3835 if (myBundleID &&
3836 strcmp( myBundleID->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0) {
3837 boolean_t updated = updateExcludeList(theInfoDict);
3838 if (!updated) {
3839 /* 25322874 */
3840 panic("Missing OSKextExcludeList dictionary\n");
3841 }
3842 break;
3843 }
3844 } // while ( (deviceTreeName = ...) )
3845
3846 OSSafeReleaseNULL(parsedXML);
3847 return;
3848 }
3849
3850 /*********************************************************************
3851 * Create a dictionary of excluded kexts from the given prelink
3852 * info (kernelcache).
3853 *********************************************************************/
3854 /* static */
3855 void
3856 OSKext::createExcludeListFromPrelinkInfo( OSArray * theInfoArray )
3857 {
3858 OSDictionary * myInfoDict = NULL;// do not release
3859 OSString * myBundleID; // do not release
3860 u_int i;
3861
3862 /* Find com.apple.driver.KextExcludeList. */
3863 for (i = 0; i < theInfoArray->getCount(); i++) {
3864 myInfoDict = OSDynamicCast(OSDictionary, theInfoArray->getObject(i));
3865 if (!myInfoDict) {
3866 continue;
3867 }
3868 myBundleID =
3869 OSDynamicCast(OSString,
3870 myInfoDict->getObject(kCFBundleIdentifierKey));
3871 if (myBundleID &&
3872 strcmp( myBundleID->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0) {
3873 boolean_t updated = updateExcludeList(myInfoDict);
3874 if (!updated) {
3875 /* 25322874 */
3876 panic("Missing OSKextExcludeList dictionary\n");
3877 }
3878 break;
3879 }
3880 } // for (i = 0; i < theInfoArray->getCount()...
3881
3882 return;
3883 }
3884
3885 /* static */
3886 boolean_t
3887 OSKext::updateExcludeList(OSDictionary *infoDict)
3888 {
3889 OSDictionary *myTempDict = NULL; // do not free
3890 OSString *myTempString = NULL;// do not free
3891 OSKextVersion newVersion = 0;
3892 boolean_t updated = false;
3893
3894 if (!infoDict) {
3895 return false;
3896 }
3897
3898 myTempDict = OSDynamicCast(OSDictionary, infoDict->getObject("OSKextExcludeList"));
3899 if (!myTempDict) {
3900 return false;
3901 }
3902
3903 myTempString = OSDynamicCast(OSString, infoDict->getObject(kCFBundleVersionKey));
3904 if (!myTempString) {
3905 return false;
3906 }
3907
3908 newVersion = OSKextParseVersionString(myTempString->getCStringNoCopy());
3909 if (newVersion == 0) {
3910 return false;
3911 }
3912
3913 IORecursiveLockLock(sKextLock);
3914
3915 if (newVersion > sExcludeListVersion) {
3916 OSSafeReleaseNULL(sExcludeListByID);
3917 sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0);
3918 sExcludeListVersion = newVersion;
3919 updated = true;
3920 }
3921
3922 IORecursiveLockUnlock(sKextLock);
3923 return updated;
3924 }
3925
3926 #if PRAGMA_MARK
3927 #pragma mark Accessors
3928 #endif
3929 /*********************************************************************
3930 *********************************************************************/
3931 const OSSymbol *
3932 OSKext::getIdentifier(void)
3933 {
3934 return bundleID;
3935 }
3936
3937 /*********************************************************************
3938 * A kext must have a bundle identifier to even survive initialization;
3939 * this is guaranteed to exist past then.
3940 *********************************************************************/
3941 const char *
3942 OSKext::getIdentifierCString(void)
3943 {
3944 return bundleID->getCStringNoCopy();
3945 }
3946
3947 /*********************************************************************
3948 *********************************************************************/
3949 OSKextVersion
3950 OSKext::getVersion(void)
3951 {
3952 return version;
3953 }
3954
3955 /*********************************************************************
3956 *********************************************************************/
3957 OSKextVersion
3958 OSKext::getCompatibleVersion(void)
3959 {
3960 return compatibleVersion;
3961 }
3962
3963 /*********************************************************************
3964 *********************************************************************/
3965 bool
3966 OSKext::isLibrary(void)
3967 {
3968 return getCompatibleVersion() > 0;
3969 }
3970
3971 /*********************************************************************
3972 *********************************************************************/
3973 bool
3974 OSKext::isCompatibleWithVersion(OSKextVersion aVersion)
3975 {
3976 if ((compatibleVersion > -1 && version > -1) &&
3977 (compatibleVersion <= version && aVersion <= version)) {
3978 return true;
3979 }
3980 return false;
3981 }
3982
3983 /*********************************************************************
3984 *********************************************************************/
3985 bool
3986 OSKext::declaresExecutable(void)
3987 {
3988 return getPropertyForHostArch(kCFBundleExecutableKey) != NULL;
3989 }
3990
3991 /*********************************************************************
3992 *********************************************************************/
3993 OSData *
3994 OSKext::getExecutable(void)
3995 {
3996 OSData * result = NULL;
3997 OSData * extractedExecutable = NULL; // must release
3998 OSData * mkextExecutableRef = NULL;// do not release
3999
4000 if (flags.builtin) {
4001 return sKernelKext->linkedExecutable;
4002 }
4003
4004 result = OSDynamicCast(OSData, infoDict->getObject(_kOSKextExecutableKey));
4005 if (result) {
4006 goto finish;
4007 }
4008
4009 mkextExecutableRef = OSDynamicCast(OSData,
4010 getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey));
4011
4012 if (mkextExecutableRef) {
4013 MkextEntryRef * mkextEntryRef = (MkextEntryRef *)
4014 mkextExecutableRef->getBytesNoCopy();
4015 uint32_t mkextVersion = MKEXT_GET_VERSION(mkextEntryRef->mkext);
4016 if (mkextVersion == MKEXT_VERS_2) {
4017 mkext2_file_entry * fileinfo =
4018 (mkext2_file_entry *)mkextEntryRef->fileinfo;
4019 uint32_t compressedSize = MKEXT2_GET_ENTRY_COMPSIZE(fileinfo);
4020 uint32_t fullSize = MKEXT2_GET_ENTRY_FULLSIZE(fileinfo);
4021 extractedExecutable = extractMkext2FileData(
4022 MKEXT2_GET_ENTRY_DATA(fileinfo), "executable",
4023 compressedSize, fullSize);
4024 } else {
4025 OSKextLog(this, kOSKextLogErrorLevel |
4026 kOSKextLogArchiveFlag,
4027 "Kext %s - unknown mkext version 0x%x for executable.",
4028 getIdentifierCString(), mkextVersion);
4029 }
4030
4031 /* Regardless of success, remove the mkext executable,
4032 * and drop one reference on the mkext. (setExecutable() does not
4033 * replace, it removes, or panics if asked to replace.)
4034 */
4035 infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
4036 infoDict->removeObject(_kOSKextExecutableExternalDataKey);
4037
4038 if (extractedExecutable && extractedExecutable->getLength()) {
4039 if (!setExecutable(extractedExecutable)) {
4040 goto finish;
4041 }
4042 result = extractedExecutable;
4043 } else {
4044 goto finish;
4045 }
4046 }
4047
4048 finish:
4049
4050 OSSafeReleaseNULL(extractedExecutable);
4051
4052 return result;
4053 }
4054
4055 /*********************************************************************
4056 *********************************************************************/
4057 bool
4058 OSKext::isInterface(void)
4059 {
4060 return flags.interface;
4061 }
4062
4063 /*********************************************************************
4064 *********************************************************************/
4065 bool
4066 OSKext::isKernel(void)
4067 {
4068 return this == sKernelKext;
4069 }
4070
4071 /*********************************************************************
4072 *********************************************************************/
4073 bool
4074 OSKext::isKernelComponent(void)
4075 {
4076 return flags.kernelComponent ? true : false;
4077 }
4078
4079 /*********************************************************************
4080 *********************************************************************/
4081 bool
4082 OSKext::isExecutable(void)
4083 {
4084 return !isKernel() && !isInterface() && declaresExecutable();
4085 }
4086
4087 /*********************************************************************
4088 * We might want to check this recursively for all dependencies,
4089 * since a subtree of dependencies could get loaded before we hit
4090 * a dependency that isn't safe-boot-loadable.
4091 *
4092 * xxx - Might want to return false if OSBundleEnableKextLogging or
4093 * OSBundleDebugLevel
4094 * or IOKitDebug is nonzero too (we used to do that, but I don't see
4095 * the point except it's usually development drivers, which might
4096 * cause panics on startup, that have those properties). Heh; could
4097 * use a "kx" boot-arg!
4098 *********************************************************************/
4099 bool
4100 OSKext::isLoadableInSafeBoot(void)
4101 {
4102 bool result = false;
4103 OSString * required = NULL; // do not release
4104
4105 if (isKernel()) {
4106 result = true;
4107 goto finish;
4108 }
4109
4110 required = OSDynamicCast(OSString,
4111 getPropertyForHostArch(kOSBundleRequiredKey));
4112 if (!required) {
4113 goto finish;
4114 }
4115 if (required->isEqualTo(kOSBundleRequiredRoot) ||
4116 required->isEqualTo(kOSBundleRequiredLocalRoot) ||
4117 required->isEqualTo(kOSBundleRequiredNetworkRoot) ||
4118 required->isEqualTo(kOSBundleRequiredSafeBoot) ||
4119 required->isEqualTo(kOSBundleRequiredConsole)) {
4120 result = true;
4121 }
4122
4123 finish:
4124 return result;
4125 }
4126
4127 /*********************************************************************
4128 *********************************************************************/
4129 bool
4130 OSKext::isPrelinked(void)
4131 {
4132 return flags.prelinked ? true : false;
4133 }
4134
4135 /*********************************************************************
4136 *********************************************************************/
4137 bool
4138 OSKext::isLoaded(void)
4139 {
4140 return flags.loaded ? true : false;
4141 }
4142
4143 /*********************************************************************
4144 *********************************************************************/
4145 bool
4146 OSKext::isStarted(void)
4147 {
4148 return flags.started ? true : false;
4149 }
4150
4151 /*********************************************************************
4152 *********************************************************************/
4153 bool
4154 OSKext::isCPPInitialized(void)
4155 {
4156 return flags.CPPInitialized;
4157 }
4158
4159 /*********************************************************************
4160 *********************************************************************/
4161 void
4162 OSKext::setCPPInitialized(bool initialized)
4163 {
4164 flags.CPPInitialized = initialized;
4165 }
4166
4167 /*********************************************************************
4168 *********************************************************************/
4169 uint32_t
4170 OSKext::getLoadTag(void)
4171 {
4172 return loadTag;
4173 }
4174
4175 /*********************************************************************
4176 *********************************************************************/
4177 void
4178 OSKext::getSizeInfo(uint32_t *loadSize, uint32_t *wiredSize)
4179 {
4180 if (linkedExecutable) {
4181 *loadSize = linkedExecutable->getLength();
4182
4183 /* If we have a kmod_info struct, calculated the wired size
4184 * from that. Otherwise it's the full load size.
4185 */
4186 if (kmod_info) {
4187 *wiredSize = *loadSize - kmod_info->hdr_size;
4188 } else {
4189 *wiredSize = *loadSize;
4190 }
4191 } else {
4192 *wiredSize = 0;
4193 *loadSize = 0;
4194 }
4195 }
4196
4197 /*********************************************************************
4198 *********************************************************************/
4199 OSData *
4200 OSKext::copyUUID(void)
4201 {
4202 OSData * result = NULL;
4203 OSData * theExecutable = NULL;// do not release
4204 const kernel_mach_header_t * header;
4205
4206 /* An interface kext doesn't have a linked executable with an LC_UUID,
4207 * we create one when it's linked.
4208 */
4209 if (interfaceUUID) {
4210 result = interfaceUUID;
4211 result->retain();
4212 goto finish;
4213 }
4214
4215 if (flags.builtin || isInterface()) {
4216 return sKernelKext->copyUUID();
4217 }
4218
4219 /* For real kexts, try to get the UUID from the linked executable,
4220 * or if is hasn't been linked yet, the unrelocated executable.
4221 */
4222 theExecutable = linkedExecutable;
4223 if (!theExecutable) {
4224 theExecutable = getExecutable();
4225 }
4226 if (!theExecutable) {
4227 goto finish;
4228 }
4229
4230 header = (const kernel_mach_header_t *)theExecutable->getBytesNoCopy();
4231 result = copyMachoUUID(header);
4232
4233 finish:
4234 return result;
4235 }
4236
4237 /*********************************************************************
4238 *********************************************************************/
4239 OSData *
4240 OSKext::copyTextUUID(void)
4241 {
4242 if (flags.builtin) {
4243 return copyMachoUUID((const kernel_mach_header_t *)kmod_info->address);
4244 }
4245 return copyUUID();
4246 }
4247
4248 /*********************************************************************
4249 *********************************************************************/
4250 OSData *
4251 OSKext::copyMachoUUID(const kernel_mach_header_t * header)
4252 {
4253 OSData * result = NULL;
4254 const struct load_command * load_cmd = NULL;
4255 const struct uuid_command * uuid_cmd = NULL;
4256 uint32_t i;
4257
4258 load_cmd = (const struct load_command *)&header[1];
4259
4260 if (header->magic != MH_MAGIC_KERNEL) {
4261 OSKextLog(NULL,
4262 kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4263 "%s: bad header %p",
4264 __func__,
4265 header);
4266 goto finish;
4267 }
4268
4269 for (i = 0; i < header->ncmds; i++) {
4270 if (load_cmd->cmd == LC_UUID) {
4271 uuid_cmd = (struct uuid_command *)load_cmd;
4272 result = OSData::withBytes(uuid_cmd->uuid, sizeof(uuid_cmd->uuid));
4273 goto finish;
4274 }
4275 load_cmd = (struct load_command *)((caddr_t)load_cmd + load_cmd->cmdsize);
4276 }
4277
4278 finish:
4279 return result;
4280 }
4281
4282 /*********************************************************************
4283 *********************************************************************/
4284 #if defined (__arm__)
4285 #include <arm/arch.h>
4286 #endif
4287
4288 #if defined (__x86_64__)
4289 #define ARCHNAME "x86_64"
4290 #elif defined (__arm64__)
4291 #define ARCHNAME "arm64"
4292 #elif defined (__arm__)
4293
4294 #if defined (__ARM_ARCH_7S__)
4295 #define ARCHNAME "armv7s"
4296 #elif defined (__ARM_ARCH_7F__)
4297 #define ARCHNAME "armv7f"
4298 #elif defined (__ARM_ARCH_7K__)
4299 #define ARCHNAME "armv7k"
4300 #elif defined (_ARM_ARCH_7) /* umbrella for all remaining */
4301 #define ARCHNAME "armv7"
4302 #elif defined (_ARM_ARCH_6) /* umbrella for all armv6 */
4303 #define ARCHNAME "armv6"
4304 #endif
4305
4306 #elif defined (__arm64__)
4307 #define ARCHNAME "arm64"
4308 #else
4309 #error architecture not supported
4310 #endif
4311
4312 #define ARCH_SEPARATOR_CHAR '_'
4313
4314 static char *
4315 makeHostArchKey(const char * key, uint32_t * keySizeOut)
4316 {
4317 char * result = NULL;
4318 uint32_t keyLength = strlen(key);
4319 uint32_t keySize;
4320
4321 /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
4322 */
4323 keySize = 1 + 1 + strlen(key) + strlen(ARCHNAME);
4324 result = (char *)kalloc_tag(keySize, VM_KERN_MEMORY_OSKEXT);
4325 if (!result) {
4326 goto finish;
4327 }
4328 strlcpy(result, key, keySize);
4329 result[keyLength++] = ARCH_SEPARATOR_CHAR;
4330 result[keyLength] = '\0';
4331 strlcat(result, ARCHNAME, keySize);
4332 *keySizeOut = keySize;
4333
4334 finish:
4335 return result;
4336 }
4337
4338 /*********************************************************************
4339 *********************************************************************/
4340 OSObject *
4341 OSKext::getPropertyForHostArch(const char * key)
4342 {
4343 OSObject * result = NULL;// do not release
4344 uint32_t hostArchKeySize = 0;
4345 char * hostArchKey = NULL;// must kfree
4346
4347 if (!key || !infoDict) {
4348 goto finish;
4349 }
4350
4351 /* Some properties are not allowed to be arch-variant:
4352 * - Any CFBundle... property.
4353 * - OSBundleIsInterface.
4354 * - OSKernelResource.
4355 */
4356 if (STRING_HAS_PREFIX(key, "OS") ||
4357 STRING_HAS_PREFIX(key, "IO")) {
4358 hostArchKey = makeHostArchKey(key, &hostArchKeySize);
4359 if (!hostArchKey) {
4360 OSKextLog(/* kext (this isn't about a kext) */ NULL,
4361 kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4362 "Allocation failure.");
4363 goto finish;
4364 }
4365 result = infoDict->getObject(hostArchKey);
4366 }
4367
4368 if (!result) {
4369 result = infoDict->getObject(key);
4370 }
4371
4372 finish:
4373 if (hostArchKey) {
4374 kfree(hostArchKey, hostArchKeySize);
4375 }
4376 return result;
4377 }
4378
4379 #if PRAGMA_MARK
4380 #pragma mark Load/Start/Stop/Unload
4381 #endif
4382
4383 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
4384
4385 /*********************************************************************
4386 * sExcludeListByID is a dictionary with keys / values of:
4387 * key = bundleID string of kext we will not allow to load
4388 * value = version string(s) of the kext that is to be denied loading.
4389 * The version strings can be comma delimited. For example if kext
4390 * com.foocompany.fookext has two versions that we want to deny
4391 * loading then the version strings might look like:
4392 * 1.0.0, 1.0.1
4393 * If the current fookext has a version of 1.0.0 OR 1.0.1 we will
4394 * not load the kext.
4395 *
4396 * Value may also be in the form of "LE 2.0.0" (version numbers
4397 * less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
4398 * number less than 2.0.0 will not load)
4399 *
4400 * NOTE - we cannot use the characters "<=" or "<" because we have code
4401 * that serializes plists and treats '<' as a special character.
4402 *********************************************************************/
4403 bool
4404 OSKext::isInExcludeList(void)
4405 {
4406 OSString * versionString = NULL;// do not release
4407 char * versionCString = NULL;// do not free
4408 size_t i;
4409 boolean_t wantLessThan = false;
4410 boolean_t wantLessThanEqualTo = false;
4411 boolean_t isInExcludeList = true;
4412 char myBuffer[32];
4413
4414 IORecursiveLockLock(sKextLock);
4415
4416 if (!sExcludeListByID) {
4417 isInExcludeList = false;
4418 } else {
4419 /* look up by bundleID in our exclude list and if found get version
4420 * string (or strings) that we will not allow to load
4421 */
4422 versionString = OSDynamicCast(OSString, sExcludeListByID->getObject(bundleID));
4423 if (versionString == NULL || versionString->getLength() > (sizeof(myBuffer) - 1)) {
4424 isInExcludeList = false;
4425 }
4426 }
4427
4428 IORecursiveLockUnlock(sKextLock);
4429
4430 if (!isInExcludeList) {
4431 return false;
4432 }
4433
4434 /* parse version strings */
4435 versionCString = (char *) versionString->getCStringNoCopy();
4436
4437 /* look for "LT" or "LE" form of version string, must be in first two
4438 * positions.
4439 */
4440 if (*versionCString == 'L' && *(versionCString + 1) == 'T') {
4441 wantLessThan = true;
4442 versionCString += 2;
4443 } else if (*versionCString == 'L' && *(versionCString + 1) == 'E') {
4444 wantLessThanEqualTo = true;
4445 versionCString += 2;
4446 }
4447
4448 for (i = 0; *versionCString != 0x00; versionCString++) {
4449 /* skip whitespace */
4450 if (isWhiteSpace(*versionCString)) {
4451 continue;
4452 }
4453
4454 /* peek ahead for version string separator or null terminator */
4455 if (*(versionCString + 1) == ',' || *(versionCString + 1) == 0x00) {
4456 /* OK, we have a version string */
4457 myBuffer[i++] = *versionCString;
4458 myBuffer[i] = 0x00;
4459
4460 OSKextVersion excludeVers;
4461 excludeVers = OSKextParseVersionString(myBuffer);
4462
4463 if (wantLessThanEqualTo) {
4464 if (version <= excludeVers) {
4465 return true;
4466 }
4467 } else if (wantLessThan) {
4468 if (version < excludeVers) {
4469 return true;
4470 }
4471 } else if (version == excludeVers) {
4472 return true;
4473 }
4474
4475 /* reset for the next (if any) version string */
4476 i = 0;
4477 wantLessThan = false;
4478 wantLessThanEqualTo = false;
4479 } else {
4480 /* save valid version character */
4481 myBuffer[i++] = *versionCString;
4482
4483 /* make sure bogus version string doesn't overrun local buffer */
4484 if (i >= sizeof(myBuffer)) {
4485 break;
4486 }
4487 }
4488 }
4489
4490 return false;
4491 }
4492
4493 /*********************************************************************
4494 *********************************************************************/
4495 /* static */
4496 OSReturn
4497 OSKext::loadKextWithIdentifier(
4498 const char * kextIdentifierCString,
4499 Boolean allowDeferFlag,
4500 Boolean delayAutounloadFlag,
4501 OSKextExcludeLevel startOpt,
4502 OSKextExcludeLevel startMatchingOpt,
4503 OSArray * personalityNames)
4504 {
4505 OSReturn result = kOSReturnError;
4506 OSString * kextIdentifier = NULL; // must release
4507
4508 kextIdentifier = OSString::withCString(kextIdentifierCString);
4509 if (!kextIdentifier) {
4510 result = kOSKextReturnNoMemory;
4511 goto finish;
4512 }
4513 result = OSKext::loadKextWithIdentifier(kextIdentifier,
4514 allowDeferFlag, delayAutounloadFlag,
4515 startOpt, startMatchingOpt, personalityNames);
4516
4517 finish:
4518 OSSafeReleaseNULL(kextIdentifier);
4519 return result;
4520 }
4521
4522 /*********************************************************************
4523 *********************************************************************/
4524 OSReturn
4525 OSKext::loadKextWithIdentifier(
4526 OSString * kextIdentifier,
4527 Boolean allowDeferFlag,
4528 Boolean delayAutounloadFlag,
4529 OSKextExcludeLevel startOpt,
4530 OSKextExcludeLevel startMatchingOpt,
4531 OSArray * personalityNames)
4532 {
4533 OSReturn result = kOSReturnError;
4534 OSReturn pingResult = kOSReturnError;
4535 OSKext * theKext = NULL;// do not release
4536 OSDictionary * loadRequest = NULL;// must release
4537 const OSSymbol * kextIdentifierSymbol = NULL;// must release
4538
4539 IORecursiveLockLock(sKextLock);
4540
4541 if (!kextIdentifier) {
4542 result = kOSKextReturnInvalidArgument;
4543 goto finish;
4544 }
4545
4546 OSKext::recordIdentifierRequest(kextIdentifier);
4547
4548 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
4549 if (!theKext) {
4550 if (!allowDeferFlag) {
4551 OSKextLog(/* kext */ NULL,
4552 kOSKextLogErrorLevel |
4553 kOSKextLogLoadFlag,
4554 "Can't load kext %s - not found.",
4555 kextIdentifier->getCStringNoCopy());
4556 goto finish;
4557 }
4558
4559 if (!sKernelRequestsEnabled) {
4560 OSKextLog(theKext,
4561 kOSKextLogErrorLevel |
4562 kOSKextLogLoadFlag,
4563 "Can't load kext %s - requests to user space are disabled.",
4564 kextIdentifier->getCStringNoCopy());
4565 result = kOSKextReturnDisabled;
4566 goto finish;
4567 }
4568
4569 /* Create a new request unless one is already sitting
4570 * in sKernelRequests for this bundle identifier
4571 */
4572 kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
4573 if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol)) {
4574 result = _OSKextCreateRequest(kKextRequestPredicateRequestLoad,
4575 &loadRequest);
4576 if (result != kOSReturnSuccess) {
4577 goto finish;
4578 }
4579 if (!_OSKextSetRequestArgument(loadRequest,
4580 kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
4581 result = kOSKextReturnNoMemory;
4582 goto finish;
4583 }
4584 if (!sKernelRequests->setObject(loadRequest)) {
4585 result = kOSKextReturnNoMemory;
4586 goto finish;
4587 }
4588
4589 if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol)) {
4590 result = kOSKextReturnNoMemory;
4591 goto finish;
4592 }
4593
4594 OSKextLog(theKext,
4595 kOSKextLogDebugLevel |
4596 kOSKextLogLoadFlag,
4597 "Kext %s not found; queued load request to user space.",
4598 kextIdentifier->getCStringNoCopy());
4599 }
4600
4601 pingResult = OSKext::pingKextd();
4602 if (pingResult == kOSKextReturnDisabled) {
4603 OSKextLog(/* kext */ NULL,
4604 ((sPrelinkBoot) ? kOSKextLogDebugLevel : kOSKextLogErrorLevel) |
4605 kOSKextLogLoadFlag,
4606 "Kext %s might not load - kextd is currently unavailable.",
4607 kextIdentifier->getCStringNoCopy());
4608 }
4609
4610 result = kOSKextReturnDeferred;
4611 goto finish;
4612 }
4613
4614 result = theKext->load(startOpt, startMatchingOpt, personalityNames);
4615
4616 if (result != kOSReturnSuccess) {
4617 OSKextLog(theKext,
4618 kOSKextLogErrorLevel |
4619 kOSKextLogLoadFlag,
4620 "Failed to load kext %s (error 0x%x).",
4621 kextIdentifier->getCStringNoCopy(), (int)result);
4622
4623 OSKext::removeKext(theKext,
4624 /* terminateService/removePersonalities */ true);
4625 goto finish;
4626 }
4627
4628 if (delayAutounloadFlag) {
4629 OSKextLog(theKext,
4630 kOSKextLogProgressLevel |
4631 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
4632 "Setting delayed autounload for %s.",
4633 kextIdentifier->getCStringNoCopy());
4634 theKext->flags.delayAutounload = 1;
4635 }
4636
4637 finish:
4638 OSSafeReleaseNULL(loadRequest);
4639 OSSafeReleaseNULL(kextIdentifierSymbol);
4640
4641 IORecursiveLockUnlock(sKextLock);
4642
4643 return result;
4644 }
4645
4646 /*********************************************************************
4647 *********************************************************************/
4648 /* static */
4649 void
4650 OSKext::recordIdentifierRequest(
4651 OSString * kextIdentifier)
4652 {
4653 const OSSymbol * kextIdentifierSymbol = NULL; // must release
4654 bool fail = false;
4655
4656 if (!sAllKextLoadIdentifiers || !kextIdentifier) {
4657 goto finish;
4658 }
4659
4660 kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
4661 if (!kextIdentifierSymbol) {
4662 // xxx - this is really a basic alloc failure
4663 fail = true;
4664 goto finish;
4665 }
4666
4667 IORecursiveLockLock(sKextLock);
4668 if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol)) {
4669 if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol)) {
4670 fail = true;
4671 } else {
4672 // xxx - need to find a way to associate this whole func w/the kext
4673 OSKextLog(/* kext */ NULL,
4674 // xxx - check level
4675 kOSKextLogStepLevel |
4676 kOSKextLogArchiveFlag,
4677 "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
4678 kextIdentifier->getCStringNoCopy());
4679 }
4680 }
4681 IORecursiveLockUnlock(sKextLock);
4682
4683 finish:
4684
4685 if (fail) {
4686 OSKextLog(/* kext */ NULL,
4687 kOSKextLogErrorLevel |
4688 kOSKextLogArchiveFlag,
4689 "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
4690 kextIdentifier->getCStringNoCopy());
4691 }
4692 OSSafeReleaseNULL(kextIdentifierSymbol);
4693 return;
4694 }
4695
4696 /*********************************************************************
4697 *********************************************************************/
4698 OSReturn
4699 OSKext::load(
4700 OSKextExcludeLevel startOpt,
4701 OSKextExcludeLevel startMatchingOpt,
4702 OSArray * personalityNames)
4703 {
4704 OSReturn result = kOSReturnError;
4705 kern_return_t kxldResult;
4706 OSKextExcludeLevel dependenciesStartOpt = startOpt;
4707 OSKextExcludeLevel dependenciesStartMatchingOpt = startMatchingOpt;
4708 unsigned int i, count;
4709 Boolean alreadyLoaded = false;
4710 OSKext * lastLoadedKext = NULL;
4711
4712 if (isInExcludeList()) {
4713 OSKextLog(this,
4714 kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
4715 kOSKextLogLoadFlag,
4716 "Kext %s is in exclude list, not loadable",
4717 getIdentifierCString());
4718
4719 result = kOSKextReturnNotLoadable;
4720 goto finish;
4721 }
4722
4723 if (isLoaded()) {
4724 alreadyLoaded = true;
4725 result = kOSReturnSuccess;
4726
4727 OSKextLog(this,
4728 kOSKextLogDebugLevel |
4729 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
4730 "Kext %s is already loaded.",
4731 getIdentifierCString());
4732 goto loaded;
4733 }
4734
4735 #if CONFIG_MACF
4736 if (current_task() != kernel_task) {
4737 int macCheckResult = 0;
4738 kauth_cred_t cred = NULL;
4739
4740 cred = kauth_cred_get_with_ref();
4741 macCheckResult = mac_kext_check_load(cred, getIdentifierCString());
4742 kauth_cred_unref(&cred);
4743
4744 if (macCheckResult != 0) {
4745 result = kOSReturnError;
4746 OSKextLog(this,
4747 kOSKextLogErrorLevel | kOSKextLogLoadFlag,
4748 "Failed to load kext %s (MAC policy error 0x%x).",
4749 getIdentifierCString(), macCheckResult);
4750 goto finish;
4751 }
4752 }
4753 #endif
4754
4755 if (!sLoadEnabled) {
4756 OSKextLog(this,
4757 kOSKextLogErrorLevel |
4758 kOSKextLogLoadFlag,
4759 "Kext loading is disabled (attempt to load kext %s).",
4760 getIdentifierCString());
4761 result = kOSKextReturnDisabled;
4762 goto finish;
4763 }
4764
4765 /* If we've pushed the next available load tag to the invalid value,
4766 * we can't load any more kexts.
4767 */
4768 if (sNextLoadTag == kOSKextInvalidLoadTag) {
4769 OSKextLog(this,
4770 kOSKextLogErrorLevel |
4771 kOSKextLogLoadFlag,
4772 "Can't load kext %s - no more load tags to assign.",
4773 getIdentifierCString());
4774 result = kOSKextReturnNoResources;
4775 goto finish;
4776 }
4777
4778 /* This is a bit of a hack, because we shouldn't be handling
4779 * personalities within the load function.
4780 */
4781 if (!declaresExecutable()) {
4782 /* There is a special case where a non-executable kext can be loaded: the
4783 * AppleKextExcludeList. Detect that special kext by bundle identifier and
4784 * load its metadata into the global data structures, if appropriate
4785 */
4786 if (strcmp(getIdentifierCString(), "com.apple.driver.KextExcludeList") == 0) {
4787 boolean_t updated = updateExcludeList(infoDict);
4788 if (updated) {
4789 OSKextLog(this,
4790 kOSKextLogDebugLevel | kOSKextLogLoadFlag,
4791 "KextExcludeList was updated to version: %lld", sExcludeListVersion);
4792 }
4793 }
4794 result = kOSReturnSuccess;
4795 goto loaded;
4796 }
4797
4798 /* Are we in safe boot?
4799 */
4800 if (sSafeBoot && !isLoadableInSafeBoot()) {
4801 OSKextLog(this,
4802 kOSKextLogErrorLevel |
4803 kOSKextLogLoadFlag,
4804 "Can't load kext %s - not loadable during safe boot.",
4805 getIdentifierCString());
4806 result = kOSKextReturnBootLevel;
4807 goto finish;
4808 }
4809
4810 OSKextLog(this,
4811 kOSKextLogProgressLevel | kOSKextLogLoadFlag,
4812 "Loading kext %s.",
4813 getIdentifierCString());
4814
4815 if (!sKxldContext) {
4816 kxldResult = kxld_create_context(&sKxldContext, &kern_allocate,
4817 &kxld_log_callback, /* Flags */ (KXLDFlags) 0,
4818 /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0);
4819 if (kxldResult) {
4820 OSKextLog(this,
4821 kOSKextLogErrorLevel |
4822 kOSKextLogLoadFlag | kOSKextLogLinkFlag,
4823 "Can't load kext %s - failed to create link context.",
4824 getIdentifierCString());
4825 result = kOSKextReturnNoMemory;
4826 goto finish;
4827 }
4828 }
4829
4830 /* We only need to resolve dependencies once for the whole graph, but
4831 * resolveDependencies will just return if there's no work to do, so it's
4832 * safe to call it more than once.
4833 */
4834 if (!resolveDependencies()) {
4835 // xxx - check resolveDependencies() for log msg
4836 OSKextLog(this,
4837 kOSKextLogErrorLevel |
4838 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
4839 "Can't load kext %s - failed to resolve library dependencies.",
4840 getIdentifierCString());
4841 result = kOSKextReturnDependencies;
4842 goto finish;
4843 }
4844
4845 /* If we are excluding just the kext being loaded now (and not its
4846 * dependencies), drop the exclusion level to none so dependencies
4847 * start and/or add their personalities.
4848 */
4849 if (dependenciesStartOpt == kOSKextExcludeKext) {
4850 dependenciesStartOpt = kOSKextExcludeNone;
4851 }
4852
4853 if (dependenciesStartMatchingOpt == kOSKextExcludeKext) {
4854 dependenciesStartMatchingOpt = kOSKextExcludeNone;
4855 }
4856
4857 /* Load the dependencies, recursively.
4858 */
4859 count = getNumDependencies();
4860 for (i = 0; i < count; i++) {
4861 OSKext * dependency = OSDynamicCast(OSKext,
4862 dependencies->getObject(i));
4863 if (dependency == NULL) {
4864 OSKextLog(this,
4865 kOSKextLogErrorLevel |
4866 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
4867 "Internal error loading kext %s; dependency disappeared.",
4868 getIdentifierCString());
4869 result = kOSKextReturnInternalError;
4870 goto finish;
4871 }
4872
4873 /* Dependencies must be started accorting to the opt,
4874 * but not given the personality names of the main kext.
4875 */
4876 result = dependency->load(dependenciesStartOpt,
4877 dependenciesStartMatchingOpt,
4878 /* personalityNames */ NULL);
4879 if (result != KERN_SUCCESS) {
4880 OSKextLog(this,
4881 kOSKextLogErrorLevel |
4882 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
4883 "Dependency %s of kext %s failed to load.",
4884 dependency->getIdentifierCString(),
4885 getIdentifierCString());
4886
4887 OSKext::removeKext(dependency,
4888 /* terminateService/removePersonalities */ true);
4889 result = kOSKextReturnDependencyLoadError;
4890
4891 goto finish;
4892 }
4893 }
4894
4895 result = loadExecutable();
4896 if (result != KERN_SUCCESS) {
4897 goto finish;
4898 }
4899
4900 pendingPgoHead.next = &pendingPgoHead;
4901 pendingPgoHead.prev = &pendingPgoHead;
4902
4903 // The kernel PRNG is not initialized when the first kext is
4904 // loaded, so use early random
4905 uuid_generate_early_random(instance_uuid);
4906 account = IONew(OSKextAccount, 1);
4907 if (!account) {
4908 result = KERN_MEMORY_ERROR;
4909 goto finish;
4910 }
4911 bzero(account, sizeof(*account));
4912 account->loadTag = kmod_info->id;
4913 account->site.refcount = 0;
4914 account->site.flags = VM_TAG_KMOD;
4915 account->kext = this;
4916 if (gIOSurfaceIdentifier == bundleID) {
4917 vm_tag_alloc(&account->site);
4918 gIOSurfaceTag = account->site.tag;
4919 }
4920
4921 flags.loaded = true;
4922
4923 /* Add the kext to the list of loaded kexts and update the kmod_info
4924 * struct to point to that of the last loaded kext (which is the way
4925 * it's always been done, though I'd rather do them in order now).
4926 */
4927 lastLoadedKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
4928 sLoadedKexts->setObject(this);
4929
4930 /* Keep the kernel itself out of the kmod list.
4931 */
4932 if (lastLoadedKext->isKernel()) {
4933 lastLoadedKext = NULL;
4934 }
4935
4936 if (lastLoadedKext) {
4937 kmod_info->next = lastLoadedKext->kmod_info;
4938 }
4939
4940 notifyKextLoadObservers(this, kmod_info);
4941
4942 /* Make the global kmod list point at the just-loaded kext. Note that the
4943 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
4944 * although we do report it in kextstat these days by using the newer
4945 * OSArray of loaded kexts, which does contain it.
4946 *
4947 * (The OSKext object representing the kernel doesn't even have a kmod_info
4948 * struct, though I suppose we could stick a pointer to it from the
4949 * static struct in OSRuntime.cpp.)
4950 */
4951 kmod = kmod_info;
4952
4953 /* Save the list of loaded kexts in case we panic.
4954 */
4955 OSKext::saveLoadedKextPanicList();
4956
4957 if (isExecutable()) {
4958 OSKext::updateLoadedKextSummaries();
4959 savePanicString(/* isLoading */ true);
4960
4961 #if CONFIG_DTRACE
4962 registerWithDTrace();
4963 #else
4964 jettisonLinkeditSegment();
4965 #endif /* CONFIG_DTRACE */
4966
4967 #if !VM_MAPPED_KEXTS
4968 /* If there is a page (or more) worth of padding after the end
4969 * of the last data section but before the end of the data segment
4970 * then free it in the same manner the LinkeditSegment is freed
4971 */
4972 jettisonDATASegmentPadding();
4973 #endif
4974 }
4975
4976 loaded:
4977 if (isExecutable() && !flags.started) {
4978 if (startOpt == kOSKextExcludeNone) {
4979 result = start();
4980 if (result != kOSReturnSuccess) {
4981 OSKextLog(this,
4982 kOSKextLogErrorLevel | kOSKextLogLoadFlag,
4983 "Kext %s start failed (result 0x%x).",
4984 getIdentifierCString(), result);
4985 result = kOSKextReturnStartStopError;
4986 }
4987 }
4988 }
4989
4990 /* If not excluding matching, send the personalities to the kernel.
4991 * This never affects the result of the load operation.
4992 * This is a bit of a hack, because we shouldn't be handling
4993 * personalities within the load function.
4994 */
4995 if (result == kOSReturnSuccess && startMatchingOpt == kOSKextExcludeNone) {
4996 result = sendPersonalitiesToCatalog(true, personalityNames);
4997 }
4998
4999 finish:
5000
5001 /* More hack! If the kext doesn't declare an executable, even if we
5002 * "loaded" it, we have to remove any personalities naming it, or we'll
5003 * never see the registry go quiet. Errors here do not count for the
5004 * load operation itself.
5005 *
5006 * Note that in every other regard it's perfectly ok for a kext to
5007 * not declare an executable and serve only as a package for personalities
5008 * naming another kext, so we do have to allow such kexts to be "loaded"
5009 * so that those other personalities get added & matched.
5010 */
5011 if (!declaresExecutable()) {
5012 OSKextLog(this,
5013 kOSKextLogStepLevel | kOSKextLogLoadFlag,
5014 "Kext %s has no executable; removing any personalities naming it.",
5015 getIdentifierCString());
5016 removePersonalitiesFromCatalog();
5017 }
5018
5019 if (result != kOSReturnSuccess) {
5020 OSKextLog(this,
5021 kOSKextLogErrorLevel |
5022 kOSKextLogLoadFlag,
5023 "Kext %s failed to load (0x%x).",
5024 getIdentifierCString(), (int)result);
5025 } else if (!alreadyLoaded) {
5026 OSKextLog(this,
5027 kOSKextLogProgressLevel |
5028 kOSKextLogLoadFlag,
5029 "Kext %s loaded.",
5030 getIdentifierCString());
5031
5032 queueKextNotification(kKextRequestPredicateLoadNotification,
5033 OSDynamicCast(OSString, bundleID));
5034 }
5035 return result;
5036 }
5037
5038 /*********************************************************************
5039 *
5040 *********************************************************************/
5041 static char *
5042 strdup(const char * string)
5043 {
5044 char * result = NULL;
5045 size_t size;
5046
5047 if (!string) {
5048 goto finish;
5049 }
5050
5051 size = 1 + strlen(string);
5052 result = (char *)kalloc_tag(size, VM_KERN_MEMORY_OSKEXT);
5053 if (!result) {
5054 goto finish;
5055 }
5056
5057 memcpy(result, string, size);
5058
5059 finish:
5060 return result;
5061 }
5062
5063 /*********************************************************************
5064 *
5065 *********************************************************************/
5066
5067 kernel_section_t *
5068 OSKext::lookupSection(const char *segname, const char *secname)
5069 {
5070 kernel_section_t * found_section = NULL;
5071 kernel_mach_header_t * mh = NULL;
5072 kernel_segment_command_t * seg = NULL;
5073 kernel_section_t * sec = NULL;
5074
5075 if (!linkedExecutable) {
5076 return NULL;
5077 }
5078
5079 mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
5080
5081 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
5082 if (0 != strcmp(seg->segname, segname)) {
5083 continue;
5084 }
5085
5086 for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
5087 if (0 == strcmp(sec->sectname, secname)) {
5088 found_section = sec;
5089 goto out;
5090 }
5091 }
5092 }
5093
5094 out:
5095 return found_section;
5096 }
5097
5098 /*********************************************************************
5099 *
5100 *********************************************************************/
5101
5102 OSReturn
5103 OSKext::slidePrelinkedExecutable(bool doCoalesedSlides)
5104 {
5105 OSReturn result = kOSKextReturnBadData;
5106 kernel_mach_header_t * mh = NULL;
5107 kernel_segment_command_t * seg = NULL;
5108 kernel_segment_command_t * linkeditSeg = NULL;
5109 kernel_section_t * sec = NULL;
5110 char * linkeditBase = NULL;
5111 bool haveLinkeditBase = false;
5112 char * relocBase = NULL;
5113 bool haveRelocBase = false;
5114 struct dysymtab_command * dysymtab = NULL;
5115 struct linkedit_data_command * segmentSplitInfo = NULL;
5116 struct symtab_command * symtab = NULL;
5117 kernel_nlist_t * sym = NULL;
5118 struct relocation_info * reloc = NULL;
5119 uint32_t i = 0;
5120 int reloc_size;
5121 vm_offset_t new_kextsize;
5122
5123 if (linkedExecutable == NULL || flags.builtin) {
5124 result = kOSReturnSuccess;
5125 goto finish;
5126 }
5127
5128 mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
5129 segmentSplitInfo = (struct linkedit_data_command *) getcommandfromheader(mh, LC_SEGMENT_SPLIT_INFO);
5130
5131 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
5132 if (!seg->vmaddr) {
5133 continue;
5134 }
5135
5136 seg->vmaddr = ml_static_slide(seg->vmaddr);
5137
5138 #if KASLR_KEXT_DEBUG
5139 IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
5140 seg->segname,
5141 (unsigned long)ml_static_unslide(seg->vmaddr),
5142 (unsigned long)seg->vmaddr);
5143 #endif
5144
5145 if (!haveRelocBase) {
5146 relocBase = (char *) seg->vmaddr;
5147 haveRelocBase = true;
5148 }
5149 if (!strcmp(seg->segname, "__LINKEDIT")) {
5150 linkeditBase = (char *) seg->vmaddr - seg->fileoff;
5151 haveLinkeditBase = true;
5152 linkeditSeg = seg;
5153 }
5154 for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
5155 sec->addr = ml_static_slide(sec->addr);
5156
5157 #if KASLR_KEXT_DEBUG
5158 IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
5159 sec->sectname,
5160 (unsigned long)ml_static_unslide(sec->addr),
5161 (unsigned long)sec->addr);
5162 #endif
5163 }
5164 }
5165
5166 dysymtab = (struct dysymtab_command *) getcommandfromheader(mh, LC_DYSYMTAB);
5167
5168 symtab = (struct symtab_command *) getcommandfromheader(mh, LC_SYMTAB);
5169
5170 if (symtab != NULL && doCoalesedSlides == false) {
5171 /* Some pseudo-kexts have symbol tables without segments.
5172 * Ignore them. */
5173 if (symtab->nsyms > 0 && haveLinkeditBase) {
5174 sym = (kernel_nlist_t *) (linkeditBase + symtab->symoff);
5175 for (i = 0; i < symtab->nsyms; i++) {
5176 if (sym[i].n_type & N_STAB) {
5177 continue;
5178 }
5179 sym[i].n_value = ml_static_slide(sym[i].n_value);
5180
5181 #if KASLR_KEXT_DEBUG
5182 #define MAX_SYMS_TO_LOG 5
5183 if (i < MAX_SYMS_TO_LOG) {
5184 IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
5185 (unsigned long)ml_static_unslide(sym[i].n_value),
5186 (unsigned long)sym[i].n_value);
5187 }
5188 #endif
5189 }
5190 }
5191 }
5192
5193 if (dysymtab != NULL && doCoalesedSlides == false) {
5194 if (dysymtab->nextrel > 0) {
5195 OSKextLog(this,
5196 kOSKextLogErrorLevel | kOSKextLogLoadFlag |
5197 kOSKextLogLinkFlag,
5198 "Sliding kext %s: External relocations found.",
5199 getIdentifierCString());
5200 goto finish;
5201 }
5202
5203 if (dysymtab->nlocrel > 0) {
5204 if (!haveLinkeditBase) {
5205 OSKextLog(this,
5206 kOSKextLogErrorLevel | kOSKextLogLoadFlag |
5207 kOSKextLogLinkFlag,
5208 "Sliding kext %s: No linkedit segment.",
5209 getIdentifierCString());
5210 goto finish;
5211 }
5212
5213 if (!haveRelocBase) {
5214 OSKextLog(this,
5215 kOSKextLogErrorLevel | kOSKextLogLoadFlag |
5216 kOSKextLogLinkFlag,
5217 #if __x86_64__
5218 "Sliding kext %s: No writable segments.",
5219 #else
5220 "Sliding kext %s: No segments.",
5221 #endif
5222 getIdentifierCString());
5223 goto finish;
5224 }
5225
5226 reloc = (struct relocation_info *) (linkeditBase + dysymtab->locreloff);
5227 reloc_size = dysymtab->nlocrel * sizeof(struct relocation_info);
5228
5229 for (i = 0; i < dysymtab->nlocrel; i++) {
5230 if (reloc[i].r_extern != 0
5231 || reloc[i].r_type != 0
5232 || reloc[i].r_length != (sizeof(void *) == 8 ? 3 : 2)
5233 ) {
5234 OSKextLog(this,
5235 kOSKextLogErrorLevel | kOSKextLogLoadFlag |
5236 kOSKextLogLinkFlag,
5237 "Sliding kext %s: Unexpected relocation found.",
5238 getIdentifierCString());
5239 goto finish;
5240 }
5241 if (reloc[i].r_pcrel != 0) {
5242 continue;
5243 }
5244 uintptr_t *relocAddr = (uintptr_t*)(relocBase + reloc[i].r_address);
5245 *relocAddr = ml_static_slide(*relocAddr);
5246
5247 #if KASLR_KEXT_DEBUG
5248 #define MAX_DYSYMS_TO_LOG 5
5249 if (i < MAX_DYSYMS_TO_LOG) {
5250 IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
5251 (unsigned long)ml_static_unslide(*((uintptr_t *)(relocAddr))),
5252 (unsigned long)*((uintptr_t *)(relocBase + reloc[i].r_address)));
5253 }
5254 #endif
5255 }
5256
5257 /* We should free these relocations, not just delete the reference to them.
5258 * <rdar://problem/10535549> Free relocations from PIE kexts.
5259 *
5260 * For now, we do not free LINKEDIT for kexts with split segments.
5261 */
5262 new_kextsize = round_page(kmod_info->size - reloc_size);
5263 if (((kmod_info->size - new_kextsize) > PAGE_SIZE) && (!segmentSplitInfo)) {
5264 vm_offset_t endofkext = kmod_info->address + kmod_info->size;
5265 vm_offset_t new_endofkext = kmod_info->address + new_kextsize;
5266 vm_offset_t endofrelocInfo = (vm_offset_t) (((uint8_t *)reloc) + reloc_size);
5267 int bytes_remaining = endofkext - endofrelocInfo;
5268 OSData * new_osdata = NULL;
5269
5270 /* fix up symbol offsets if they are after the dsymtab local relocs */
5271 if (symtab) {
5272 if (dysymtab->locreloff < symtab->symoff) {
5273 symtab->symoff -= reloc_size;
5274 }
5275 if (dysymtab->locreloff < symtab->stroff) {
5276 symtab->stroff -= reloc_size;
5277 }
5278 }
5279 if (dysymtab->locreloff < dysymtab->extreloff) {
5280 dysymtab->extreloff -= reloc_size;
5281 }
5282
5283 /* move data behind reloc info down to new offset */
5284 if (endofrelocInfo < endofkext) {
5285 memcpy(reloc, (void *)endofrelocInfo, bytes_remaining);
5286 }
5287
5288 /* Create a new OSData for the smaller kext object and reflect
5289 * new linkedit segment size.
5290 */
5291 linkeditSeg->vmsize = round_page(linkeditSeg->vmsize - reloc_size);
5292 linkeditSeg->filesize = linkeditSeg->vmsize;
5293
5294 new_osdata = OSData::withBytesNoCopy((void *)kmod_info->address, new_kextsize);
5295 if (new_osdata) {
5296 /* Fix up kmod info and linkedExecutable.
5297 */
5298 kmod_info->size = new_kextsize;
5299 #if VM_MAPPED_KEXTS
5300 new_osdata->setDeallocFunction(osdata_kext_free);
5301 #else
5302 new_osdata->setDeallocFunction(osdata_phys_free);
5303 #endif
5304 linkedExecutable->setDeallocFunction(NULL);
5305 linkedExecutable->release();
5306 linkedExecutable = new_osdata;
5307
5308 #if VM_MAPPED_KEXTS
5309 kext_free(new_endofkext, (endofkext - new_endofkext));
5310 #else
5311 ml_static_mfree(new_endofkext, (endofkext - new_endofkext));
5312 #endif
5313 }
5314 }
5315 dysymtab->nlocrel = 0;
5316 dysymtab->locreloff = 0;
5317 }
5318 }
5319
5320 result = kOSReturnSuccess;
5321 finish:
5322 return result;
5323 }
5324
5325 /*********************************************************************
5326 * called only by load()
5327 *********************************************************************/
5328 OSReturn
5329 OSKext::loadExecutable()
5330 {
5331 OSReturn result = kOSReturnError;
5332 kern_return_t kxldResult;
5333 KXLDDependency * kxlddeps = NULL;// must kfree
5334 uint32_t num_kxlddeps = 0;
5335 OSArray * linkDependencies = NULL;// must release
5336 uint32_t numDirectDependencies = 0;
5337 uint32_t num_kmod_refs = 0;
5338 struct mach_header ** kxldHeaderPtr = NULL;// do not free
5339 struct mach_header * kxld_header = NULL;// xxx - need to free here?
5340 OSData * theExecutable = NULL;// do not release
5341 OSString * versString = NULL;// do not release
5342 const char * versCString = NULL;// do not free
5343 const char * string = NULL;// do not free
5344 unsigned int i;
5345
5346 /* We need the version string for a variety of bits below.
5347 */
5348 versString = OSDynamicCast(OSString,
5349 getPropertyForHostArch(kCFBundleVersionKey));
5350 if (!versString) {
5351 goto finish;
5352 }
5353 versCString = versString->getCStringNoCopy();
5354
5355 if (isKernelComponent()) {
5356 if (STRING_HAS_PREFIX(versCString, KERNEL_LIB_PREFIX)) {
5357 if (strncmp(versCString, KERNEL6_VERSION, strlen(KERNEL6_VERSION))) {
5358 OSKextLog(this,
5359 kOSKextLogErrorLevel |
5360 kOSKextLogLoadFlag,
5361 "Kernel component %s has incorrect version %s; "
5362 "expected %s.",
5363 getIdentifierCString(),
5364 versCString, KERNEL6_VERSION);
5365 result = kOSKextReturnInternalError;
5366 goto finish;
5367 } else if (strcmp(versCString, osrelease)) {
5368 OSKextLog(this,
5369 kOSKextLogErrorLevel |
5370 kOSKextLogLoadFlag,
5371 "Kernel component %s has incorrect version %s; "
5372 "expected %s.",
5373 getIdentifierCString(),
5374 versCString, osrelease);
5375 result = kOSKextReturnInternalError;
5376 goto finish;
5377 }
5378 }
5379 }
5380
5381 if (isPrelinked()) {
5382 goto register_kmod;
5383 }
5384
5385 /* <rdar://problem/21444003> all callers must be entitled */
5386 if (FALSE == IOTaskHasEntitlement(current_task(), "com.apple.rootless.kext-secure-management")) {
5387 OSKextLog(this,
5388 kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5389 "Not entitled to link kext '%s'",
5390 getIdentifierCString());
5391 result = kOSKextReturnNotPrivileged;
5392 goto finish;
5393 }
5394
5395 theExecutable = getExecutable();
5396 if (!theExecutable) {
5397 if (declaresExecutable()) {
5398 OSKextLog(this,
5399 kOSKextLogErrorLevel |
5400 kOSKextLogLoadFlag,
5401 "Can't load kext %s - executable is missing.",
5402 getIdentifierCString());
5403 result = kOSKextReturnValidation;
5404 goto finish;
5405 }
5406 goto register_kmod;
5407 }
5408
5409 if (isInterface()) {
5410 OSData *executableCopy = OSData::withData(theExecutable);
5411 setLinkedExecutable(executableCopy);
5412 executableCopy->release();
5413 goto register_kmod;
5414 }
5415
5416 numDirectDependencies = getNumDependencies();
5417
5418 if (flags.hasBleedthrough) {
5419 linkDependencies = dependencies;
5420 linkDependencies->retain();
5421 } else {
5422 linkDependencies = OSArray::withArray(dependencies);
5423 if (!linkDependencies) {
5424 OSKextLog(this,
5425 kOSKextLogErrorLevel |
5426 kOSKextLogLoadFlag | kOSKextLogLinkFlag,
5427 "Can't allocate link dependencies to load kext %s.",
5428 getIdentifierCString());
5429 goto finish;
5430 }
5431
5432 for (i = 0; i < numDirectDependencies; ++i) {
5433 OSKext * dependencyKext = OSDynamicCast(OSKext,
5434 dependencies->getObject(i));
5435 dependencyKext->addBleedthroughDependencies(linkDependencies);
5436 }
5437 }
5438
5439 num_kxlddeps = linkDependencies->getCount();
5440 if (!num_kxlddeps) {
5441 OSKextLog(this,
5442 kOSKextLogErrorLevel |
5443 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
5444 "Can't load kext %s - it has no library dependencies.",
5445 getIdentifierCString());
5446 goto finish;
5447 }
5448
5449 kxlddeps = (KXLDDependency *)kalloc_tag(num_kxlddeps * sizeof(*kxlddeps), VM_KERN_MEMORY_OSKEXT);
5450 if (!kxlddeps) {
5451 OSKextLog(this,
5452 kOSKextLogErrorLevel |
5453 kOSKextLogLoadFlag | kOSKextLogLinkFlag,
5454 "Can't allocate link context to load kext %s.",
5455 getIdentifierCString());
5456 goto finish;
5457 }
5458 bzero(kxlddeps, num_kxlddeps * sizeof(*kxlddeps));
5459
5460 for (i = 0; i < num_kxlddeps; ++i) {
5461 OSKext * dependency = OSDynamicCast(OSKext, linkDependencies->getObject(i));
5462
5463 if (dependency->isInterface()) {
5464 OSKext *interfaceTargetKext = NULL;
5465 OSData * interfaceTarget = NULL;
5466
5467 if (dependency->isKernelComponent()) {
5468 interfaceTargetKext = sKernelKext;
5469 interfaceTarget = sKernelKext->linkedExecutable;
5470 } else {
5471 interfaceTargetKext = OSDynamicCast(OSKext,
5472 dependency->dependencies->getObject(0));
5473
5474 interfaceTarget = interfaceTargetKext->linkedExecutable;
5475 }
5476
5477 if (!interfaceTarget) {
5478 // panic?
5479 goto finish;
5480 }
5481
5482 /* The names set here aren't actually logged yet <rdar://problem/7941514>,
5483 * it will be useful to have them in the debugger.
5484 * strdup() failing isn't critical right here so we don't check that.
5485 */
5486 kxlddeps[i].kext = (u_char *) interfaceTarget->getBytesNoCopy();
5487 kxlddeps[i].kext_size = interfaceTarget->getLength();
5488 kxlddeps[i].kext_name = strdup(interfaceTargetKext->getIdentifierCString());
5489
5490 kxlddeps[i].interface = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
5491 kxlddeps[i].interface_size = dependency->linkedExecutable->getLength();
5492 kxlddeps[i].interface_name = strdup(dependency->getIdentifierCString());
5493 } else {
5494 kxlddeps[i].kext = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
5495 kxlddeps[i].kext_size = dependency->linkedExecutable->getLength();
5496 kxlddeps[i].kext_name = strdup(dependency->getIdentifierCString());
5497 }
5498
5499 kxlddeps[i].is_direct_dependency = (i < numDirectDependencies);
5500 }
5501
5502 kxldHeaderPtr = &kxld_header;
5503
5504 #if DEBUG
5505 OSKextLog(this,
5506 kOSKextLogExplicitLevel |
5507 kOSKextLogLoadFlag | kOSKextLogLinkFlag,
5508 "Kext %s - calling kxld_link_file:\n"
5509 " kxld_context: %p\n"
5510 " executable: %p executable_length: %d\n"
5511 " user_data: %p\n"
5512 " kxld_dependencies: %p num_dependencies: %d\n"
5513 " kxld_header_ptr: %p kmod_info_ptr: %p\n",
5514 getIdentifierCString(), sKxldContext,
5515 theExecutable->getBytesNoCopy(), theExecutable->getLength(),
5516 this, kxlddeps, num_kxlddeps,
5517 kxldHeaderPtr, &kmod_info);
5518 #endif
5519
5520 /* After this call, the linkedExecutable instance variable
5521 * should exist.
5522 */
5523 kxldResult = kxld_link_file(sKxldContext,
5524 (u_char *)theExecutable->getBytesNoCopy(),
5525 theExecutable->getLength(),
5526 getIdentifierCString(), this, kxlddeps, num_kxlddeps,
5527 (u_char **)kxldHeaderPtr, (kxld_addr_t *)&kmod_info);
5528
5529 if (kxldResult != KERN_SUCCESS) {
5530 // xxx - add kxldResult here?
5531 OSKextLog(this,
5532 kOSKextLogErrorLevel |
5533 kOSKextLogLoadFlag,
5534 "Can't load kext %s - link failed.",
5535 getIdentifierCString());
5536 result = kOSKextReturnLinkError;
5537 goto finish;
5538 }
5539
5540 /* We've written data & instructions into kernel memory, so flush the data
5541 * cache and invalidate the instruction cache.
5542 * I/D caches are coherent on x86
5543 */
5544 #if !defined(__i386__) && !defined(__x86_64__)
5545 flush_dcache(kmod_info->address, kmod_info->size, false);
5546 invalidate_icache(kmod_info->address, kmod_info->size, false);
5547 #endif
5548 register_kmod:
5549
5550 if (isInterface()) {
5551 /* Whip up a fake kmod_info entry for the interface kext.
5552 */
5553 kmod_info = (kmod_info_t *)kalloc_tag(sizeof(kmod_info_t), VM_KERN_MEMORY_OSKEXT);
5554 if (!kmod_info) {
5555 result = KERN_MEMORY_ERROR;
5556 goto finish;
5557 }
5558
5559 /* A pseudokext has almost nothing in its kmod_info struct.
5560 */
5561 bzero(kmod_info, sizeof(kmod_info_t));
5562
5563 kmod_info->info_version = KMOD_INFO_VERSION;
5564
5565 /* An interface kext doesn't have a linkedExecutable, so save a
5566 * copy of the UUID out of the original executable via copyUUID()
5567 * while we still have the original executable.
5568 */
5569 interfaceUUID = copyUUID();
5570 }
5571
5572 kmod_info->id = loadTag = sNextLoadTag++;
5573 kmod_info->reference_count = 0; // KMOD_DECL... sets it to -1 (invalid).
5574
5575 /* Stamp the bundle ID and version from the OSKext over anything
5576 * resident inside the kmod_info.
5577 */
5578 string = getIdentifierCString();
5579 strlcpy(kmod_info->name, string, sizeof(kmod_info->name));
5580
5581 string = versCString;
5582 strlcpy(kmod_info->version, string, sizeof(kmod_info->version));
5583
5584 /* Add the dependencies' kmod_info structs as kmod_references.
5585 */
5586 num_kmod_refs = getNumDependencies();
5587 if (num_kmod_refs) {
5588 kmod_info->reference_list = (kmod_reference_t *)kalloc_tag(
5589 num_kmod_refs * sizeof(kmod_reference_t), VM_KERN_MEMORY_OSKEXT);
5590 if (!kmod_info->reference_list) {
5591 result = KERN_MEMORY_ERROR;
5592 goto finish;
5593 }
5594 bzero(kmod_info->reference_list,
5595 num_kmod_refs * sizeof(kmod_reference_t));
5596 for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
5597 kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
5598 OSKext * refKext = OSDynamicCast(OSKext, dependencies->getObject(refIndex));
5599 ref->info = refKext->kmod_info;
5600 ref->info->reference_count++;
5601
5602 if (refIndex + 1 < num_kmod_refs) {
5603 ref->next = kmod_info->reference_list + refIndex + 1;
5604 }
5605 }
5606 }
5607
5608 if (!isInterface() && linkedExecutable) {
5609 OSKextLog(this,
5610 kOSKextLogProgressLevel |
5611 kOSKextLogLoadFlag,
5612 "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
5613 kmod_info->name,
5614 (unsigned)kmod_info->size / PAGE_SIZE,
5615 (unsigned long)ml_static_unslide(kmod_info->address),
5616 (unsigned)kmod_info->id);
5617 }
5618
5619 /* if prelinked, VM protections are already set */
5620 result = setVMAttributes(!isPrelinked(), true);
5621 if (result != KERN_SUCCESS) {
5622 goto finish;
5623 }
5624
5625 #if KASAN
5626 if (linkedExecutable) {
5627 kasan_load_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(),
5628 linkedExecutable->getLength(), getIdentifierCString());
5629 }
5630 #else
5631 if (lookupSection(KASAN_GLOBAL_SEGNAME, KASAN_GLOBAL_SECTNAME)) {
5632 OSKextLog(this,
5633 kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5634 "KASAN: cannot load KASAN-ified kext %s on a non-KASAN kernel\n",
5635 getIdentifierCString()
5636 );
5637 result = KERN_FAILURE;
5638 goto finish;
5639 }
5640 #endif
5641
5642 result = kOSReturnSuccess;
5643
5644 finish:
5645 OSSafeReleaseNULL(linkDependencies);
5646
5647 /* Clear up locally allocated dependency info.
5648 */
5649 for (i = 0; i < num_kxlddeps; ++i) {
5650 size_t size;
5651
5652 if (kxlddeps[i].kext_name) {
5653 size = 1 + strlen(kxlddeps[i].kext_name);
5654 kfree(kxlddeps[i].kext_name, size);
5655 }
5656 if (kxlddeps[i].interface_name) {
5657 size = 1 + strlen(kxlddeps[i].interface_name);
5658 kfree(kxlddeps[i].interface_name, size);
5659 }
5660 }
5661 if (kxlddeps) {
5662 kfree(kxlddeps, (num_kxlddeps * sizeof(*kxlddeps)));
5663 }
5664
5665 /* We no longer need the unrelocated executable (which the linker
5666 * has altered anyhow).
5667 */
5668 setExecutable(NULL);
5669
5670 if (result != kOSReturnSuccess) {
5671 OSKextLog(this,
5672 kOSKextLogErrorLevel |
5673 kOSKextLogLoadFlag,
5674 "Failed to load executable for kext %s.",
5675 getIdentifierCString());
5676
5677 if (kmod_info && kmod_info->reference_list) {
5678 kfree(kmod_info->reference_list,
5679 num_kmod_refs * sizeof(kmod_reference_t));
5680 }
5681 if (isInterface()) {
5682 kfree(kmod_info, sizeof(kmod_info_t));
5683 }
5684 kmod_info = NULL;
5685 if (linkedExecutable) {
5686 linkedExecutable->release();
5687 linkedExecutable = NULL;
5688 }
5689 }
5690
5691 return result;
5692 }
5693
5694 /*********************************************************************
5695 * The linkedit segment is used by the kext linker for dependency
5696 * resolution, and by dtrace for probe initialization. We can free it
5697 * for non-library kexts, since no kexts depend on non-library kexts
5698 * by definition, once dtrace has been initialized.
5699 *********************************************************************/
5700 void
5701 OSKext::jettisonLinkeditSegment(void)
5702 {
5703 kernel_mach_header_t * machhdr = (kernel_mach_header_t *)kmod_info->address;
5704 kernel_segment_command_t * linkedit = NULL;
5705 vm_offset_t start;
5706 vm_size_t linkeditsize, kextsize;
5707 OSData * data = NULL;
5708
5709 #if NO_KEXTD
5710 /* We can free symbol tables for all embedded kexts because we don't
5711 * support runtime kext linking.
5712 */
5713 if (sKeepSymbols || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
5714 #else
5715 if (sKeepSymbols || isLibrary() || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
5716 #endif
5717 goto finish;
5718 }
5719
5720 /* Find the linkedit segment. If it's not the last segment, then freeing
5721 * it will fragment the kext into multiple VM regions, which OSKext is not
5722 * designed to handle, so we'll have to skip it.
5723 */
5724 linkedit = getsegbynamefromheader(machhdr, SEG_LINKEDIT);
5725 if (!linkedit) {
5726 goto finish;
5727 }
5728
5729 if (round_page(kmod_info->address + kmod_info->size) !=
5730 round_page(linkedit->vmaddr + linkedit->vmsize)) {
5731 goto finish;
5732 }
5733
5734 /* Create a new OSData for the smaller kext object.
5735 */
5736 linkeditsize = round_page(linkedit->vmsize);
5737 kextsize = kmod_info->size - linkeditsize;
5738 start = linkedit->vmaddr;
5739
5740 data = OSData::withBytesNoCopy((void *)kmod_info->address, kextsize);
5741 if (!data) {
5742 goto finish;
5743 }
5744
5745 /* Fix the kmod info and linkedExecutable.
5746 */
5747 kmod_info->size = kextsize;
5748
5749 #if VM_MAPPED_KEXTS
5750 data->setDeallocFunction(osdata_kext_free);
5751 #else
5752 data->setDeallocFunction(osdata_phys_free);
5753 #endif
5754 linkedExecutable->setDeallocFunction(NULL);
5755 linkedExecutable->release();
5756 linkedExecutable = data;
5757 flags.jettisonLinkeditSeg = 1;
5758
5759 /* Free the linkedit segment.
5760 */
5761 #if VM_MAPPED_KEXTS
5762 kext_free(start, linkeditsize);
5763 #else
5764 ml_static_mfree(start, linkeditsize);
5765 #endif
5766
5767 finish:
5768 return;
5769 }
5770
5771 /*********************************************************************
5772 * If there are whole pages that are unused betweem the last section
5773 * of the DATA segment and the end of the DATA segment then we can free
5774 * them
5775 *********************************************************************/
5776 void
5777 OSKext::jettisonDATASegmentPadding(void)
5778 {
5779 kernel_mach_header_t * mh;
5780 kernel_segment_command_t * dataSeg;
5781 kernel_section_t * sec, * lastSec;
5782 vm_offset_t dataSegEnd, lastSecEnd;
5783 vm_size_t padSize;
5784
5785 if (flags.builtin) {
5786 return;
5787 }
5788 mh = (kernel_mach_header_t *)kmod_info->address;
5789
5790 dataSeg = getsegbynamefromheader(mh, SEG_DATA);
5791 if (dataSeg == NULL) {
5792 return;
5793 }
5794
5795 lastSec = NULL;
5796 sec = firstsect(dataSeg);
5797 while (sec != NULL) {
5798 lastSec = sec;
5799 sec = nextsect(dataSeg, sec);
5800 }
5801
5802 if (lastSec == NULL) {
5803 return;
5804 }
5805
5806 if ((dataSeg->vmaddr != round_page(dataSeg->vmaddr)) ||
5807 (dataSeg->vmsize != round_page(dataSeg->vmsize))) {
5808 return;
5809 }
5810
5811 dataSegEnd = dataSeg->vmaddr + dataSeg->vmsize;
5812 lastSecEnd = round_page(lastSec->addr + lastSec->size);
5813
5814 if (dataSegEnd <= lastSecEnd) {
5815 return;
5816 }
5817
5818 padSize = dataSegEnd - lastSecEnd;
5819
5820 if (padSize >= PAGE_SIZE) {
5821 #if VM_MAPPED_KEXTS
5822 kext_free(lastSecEnd, padSize);
5823 #else
5824 ml_static_mfree(lastSecEnd, padSize);
5825 #endif
5826 }
5827 }
5828
5829 /*********************************************************************
5830 *********************************************************************/
5831 void
5832 OSKext::setLinkedExecutable(OSData * anExecutable)
5833 {
5834 if (linkedExecutable) {
5835 panic("Attempt to set linked executable on kext "
5836 "that already has one (%s).\n",
5837 getIdentifierCString());
5838 }
5839 linkedExecutable = anExecutable;
5840 linkedExecutable->retain();
5841 return;
5842 }
5843
5844 #if CONFIG_DTRACE
5845 /*********************************************************************
5846 * Go through all loaded kexts and tell them to register with dtrace.
5847 * The instance method only registers if necessary.
5848 *********************************************************************/
5849 /* static */
5850 void
5851 OSKext::registerKextsWithDTrace(void)
5852 {
5853 uint32_t count = sLoadedKexts->getCount();
5854 uint32_t i;
5855
5856 IORecursiveLockLock(sKextLock);
5857
5858 for (i = 0; i < count; i++) {
5859 OSKext * thisKext = NULL;// do not release
5860
5861 thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
5862 if (!thisKext || !thisKext->isExecutable()) {
5863 continue;
5864 }
5865
5866 thisKext->registerWithDTrace();
5867 }
5868
5869 IORecursiveLockUnlock(sKextLock);
5870
5871 return;
5872 }
5873
5874 extern "C" {
5875 extern int (*dtrace_modload)(struct kmod_info *, uint32_t);
5876 extern int (*dtrace_modunload)(struct kmod_info *);
5877 };
5878
5879 /*********************************************************************
5880 *********************************************************************/
5881 void
5882 OSKext::registerWithDTrace(void)
5883 {
5884 /* Register kext with dtrace. A dtrace_modload failure should not
5885 * prevent a kext from loading, so we ignore the return code.
5886 */
5887 if (!flags.dtraceInitialized && (dtrace_modload != NULL)) {
5888 uint32_t modflag = 0;
5889 OSObject * forceInit = getPropertyForHostArch("OSBundleForceDTraceInit");
5890 if (forceInit == kOSBooleanTrue) {
5891 modflag |= KMOD_DTRACE_FORCE_INIT;
5892 }
5893 if (flags.builtin) {
5894 modflag |= KMOD_DTRACE_STATIC_KEXT;
5895 }
5896
5897 (void)(*dtrace_modload)(kmod_info, modflag);
5898 flags.dtraceInitialized = true;
5899 jettisonLinkeditSegment();
5900 }
5901 return;
5902 }
5903 /*********************************************************************
5904 *********************************************************************/
5905 void
5906 OSKext::unregisterWithDTrace(void)
5907 {
5908 /* Unregister kext with dtrace. A dtrace_modunload failure should not
5909 * prevent a kext from loading, so we ignore the return code.
5910 */
5911 if (flags.dtraceInitialized && (dtrace_modunload != NULL)) {
5912 (void)(*dtrace_modunload)(kmod_info);
5913 flags.dtraceInitialized = false;
5914 }
5915 return;
5916 }
5917 #endif /* CONFIG_DTRACE */
5918
5919
5920 /*********************************************************************
5921 * called only by loadExecutable()
5922 *********************************************************************/
5923 #if !VM_MAPPED_KEXTS
5924 #if defined(__arm__) || defined(__arm64__)
5925 static inline kern_return_t
5926 OSKext_protect(
5927 vm_map_t map,
5928 vm_map_offset_t start,
5929 vm_map_offset_t end,
5930 vm_prot_t new_prot,
5931 boolean_t set_max)
5932 {
5933 #pragma unused(map)
5934 assert(map == kernel_map); // we can handle KEXTs arising from the PRELINK segment and no others
5935 assert(start <= end);
5936 if (start >= end) {
5937 return KERN_SUCCESS; // Punt segments of length zero (e.g., headers) or less (i.e., blunders)
5938 } else if (set_max) {
5939 return KERN_SUCCESS; // Punt set_max, as there's no mechanism to record that state
5940 } else {
5941 return ml_static_protect(start, end - start, new_prot);
5942 }
5943 }
5944
5945 static inline kern_return_t
5946 OSKext_wire(
5947 vm_map_t map,
5948 vm_map_offset_t start,
5949 vm_map_offset_t end,
5950 vm_prot_t access_type,
5951 boolean_t user_wire)
5952 {
5953 #pragma unused(map,start,end,access_type,user_wire)
5954 return KERN_SUCCESS; // No-op as PRELINK kexts are cemented into physical memory at boot
5955 }
5956 #else
5957 #error Unrecognized architecture
5958 #endif
5959 #else
5960 static inline kern_return_t
5961 OSKext_protect(
5962 vm_map_t map,
5963 vm_map_offset_t start,
5964 vm_map_offset_t end,
5965 vm_prot_t new_prot,
5966 boolean_t set_max)
5967 {
5968 if (start == end) { // 10538581
5969 return KERN_SUCCESS;
5970 }
5971 return vm_map_protect(map, start, end, new_prot, set_max);
5972 }
5973
5974 static inline kern_return_t
5975 OSKext_wire(
5976 vm_map_t map,
5977 vm_map_offset_t start,
5978 vm_map_offset_t end,
5979 vm_prot_t access_type,
5980 boolean_t user_wire)
5981 {
5982 return vm_map_wire_kernel(map, start, end, access_type, VM_KERN_MEMORY_KEXT, user_wire);
5983 }
5984 #endif
5985
5986 OSReturn
5987 OSKext::setVMAttributes(bool protect, bool wire)
5988 {
5989 vm_map_t kext_map = NULL;
5990 kernel_segment_command_t * seg = NULL;
5991 vm_map_offset_t start = 0;
5992 vm_map_offset_t end = 0;
5993 OSReturn result = kOSReturnError;
5994
5995 if (isInterface() || !declaresExecutable() || flags.builtin) {
5996 result = kOSReturnSuccess;
5997 goto finish;
5998 }
5999
6000 /* Get the kext's vm map */
6001 kext_map = kext_get_vm_map(kmod_info);
6002 if (!kext_map) {
6003 result = KERN_MEMORY_ERROR;
6004 goto finish;
6005 }
6006
6007 #if !VM_MAPPED_KEXTS
6008 if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO)) {
6009 /* This is a split kext in a prelinked kernelcache; we'll let the
6010 * platform code take care of protecting it. It is already wired.
6011 */
6012 /* TODO: Should this still allow protections for the first segment
6013 * to go through, in the event that we have a mix of split and
6014 * unsplit kexts?
6015 */
6016 result = KERN_SUCCESS;
6017 goto finish;
6018 }
6019 #endif
6020
6021 /* Protect the headers as read-only; they do not need to be wired */
6022 result = (protect) ? OSKext_protect(kext_map, kmod_info->address,
6023 kmod_info->address + kmod_info->hdr_size, VM_PROT_READ, TRUE)
6024 : KERN_SUCCESS;
6025 if (result != KERN_SUCCESS) {
6026 goto finish;
6027 }
6028
6029 /* Set the VM protections and wire down each of the segments */
6030 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
6031 while (seg) {
6032 #if __arm__
6033 /* We build all ARM kexts, so we can ensure they are aligned */
6034 assert((seg->vmaddr & PAGE_MASK) == 0);
6035 assert((seg->vmsize & PAGE_MASK) == 0);
6036 #endif
6037
6038 start = round_page(seg->vmaddr);
6039 end = trunc_page(seg->vmaddr + seg->vmsize);
6040
6041 if (protect) {
6042 result = OSKext_protect(kext_map, start, end, seg->maxprot, TRUE);
6043 if (result != KERN_SUCCESS) {
6044 OSKextLog(this,
6045 kOSKextLogErrorLevel |
6046 kOSKextLogLoadFlag,
6047 "Kext %s failed to set maximum VM protections "
6048 "for segment %s - 0x%x.",
6049 getIdentifierCString(), seg->segname, (int)result);
6050 goto finish;
6051 }
6052
6053 result = OSKext_protect(kext_map, start, end, seg->initprot, FALSE);
6054 if (result != KERN_SUCCESS) {
6055 OSKextLog(this,
6056 kOSKextLogErrorLevel |
6057 kOSKextLogLoadFlag,
6058 "Kext %s failed to set initial VM protections "
6059 "for segment %s - 0x%x.",
6060 getIdentifierCString(), seg->segname, (int)result);
6061 goto finish;
6062 }
6063 }
6064
6065 if (segmentShouldBeWired(seg) && wire) {
6066 result = OSKext_wire(kext_map, start, end, seg->initprot, FALSE);
6067 if (result != KERN_SUCCESS) {
6068 goto finish;
6069 }
6070 }
6071
6072 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
6073 }
6074
6075 finish:
6076 return result;
6077 }
6078
6079 /*********************************************************************
6080 *********************************************************************/
6081 boolean_t
6082 OSKext::segmentShouldBeWired(kernel_segment_command_t *seg)
6083 {
6084 return sKeepSymbols || strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname));
6085 }
6086
6087 /*********************************************************************
6088 *********************************************************************/
6089 OSReturn
6090 OSKext::validateKextMapping(bool startFlag)
6091 {
6092 OSReturn result = kOSReturnError;
6093 const char * whichOp = startFlag ? "start" : "stop";
6094 kern_return_t kern_result = 0;
6095 vm_map_t kext_map = NULL;
6096 kernel_segment_command_t * seg = NULL;
6097 mach_vm_address_t address = 0;
6098 mach_vm_size_t size = 0;
6099 uint32_t depth = 0;
6100 mach_msg_type_number_t count;
6101 vm_region_submap_short_info_data_64_t info;
6102
6103 if (flags.builtin) {
6104 return kOSReturnSuccess;
6105 }
6106
6107 count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
6108 bzero(&info, sizeof(info));
6109
6110 // xxx - do we need a distinct OSReturn value for these or is "bad data"
6111 // xxx - sufficient?
6112
6113 /* Verify that the kmod_info and start/stop pointers are non-NULL.
6114 */
6115 if (!kmod_info) {
6116 OSKextLog(this,
6117 kOSKextLogErrorLevel |
6118 kOSKextLogLoadFlag,
6119 "Kext %s - NULL kmod_info pointer.",
6120 getIdentifierCString());
6121 result = kOSKextReturnBadData;
6122 goto finish;
6123 }
6124
6125 if (startFlag) {
6126 address = (mach_vm_address_t)kmod_info->start;
6127 } else {
6128 address = (mach_vm_address_t)kmod_info->stop;
6129 }
6130
6131 if (!address) {
6132 OSKextLog(this,
6133 kOSKextLogErrorLevel |
6134 kOSKextLogLoadFlag,
6135 "Kext %s - NULL module %s pointer.",
6136 getIdentifierCString(), whichOp);
6137 result = kOSKextReturnBadData;
6138 goto finish;
6139 }
6140
6141 kext_map = kext_get_vm_map(kmod_info);
6142 depth = (kernel_map == kext_map) ? 1 : 2;
6143
6144 /* Verify that the start/stop function lies within the kext's address range.
6145 */
6146 if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO)) {
6147 /* This will likely be how we deal with split kexts; walk the segments to
6148 * check that the function lies inside one of the segments of this kext.
6149 */
6150 for (seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
6151 seg != NULL;
6152 seg = nextsegfromheader((kernel_mach_header_t *)kmod_info->address, seg)) {
6153 if ((address >= seg->vmaddr) && address < (seg->vmaddr + seg->vmsize)) {
6154 break;
6155 }
6156 }
6157
6158 if (!seg) {
6159 OSKextLog(this,
6160 kOSKextLogErrorLevel |
6161 kOSKextLogLoadFlag,
6162 "Kext %s module %s pointer is outside of kext range "
6163 "(%s %p - kext starts at %p).",
6164 getIdentifierCString(),
6165 whichOp,
6166 whichOp,
6167 (void *)ml_static_unslide(address),
6168 (void *)ml_static_unslide(kmod_info->address));
6169 result = kOSKextReturnBadData;
6170 goto finish;
6171 }
6172
6173 seg = NULL;
6174 } else {
6175 if (address < kmod_info->address + kmod_info->hdr_size ||
6176 kmod_info->address + kmod_info->size <= address) {
6177 OSKextLog(this,
6178 kOSKextLogErrorLevel |
6179 kOSKextLogLoadFlag,
6180 "Kext %s module %s pointer is outside of kext range "
6181 "(%s %p - kext at %p-%p).",
6182 getIdentifierCString(),
6183 whichOp,
6184 whichOp,
6185 (void *)ml_static_unslide(address),
6186 (void *)ml_static_unslide(kmod_info->address),
6187 (void *)(ml_static_unslide(kmod_info->address) + kmod_info->size));
6188 result = kOSKextReturnBadData;
6189 goto finish;
6190 }
6191 }
6192
6193 /* Only do these checks before calling the start function;
6194 * If anything goes wrong with the mapping while the kext is running,
6195 * we'll likely have panicked well before any attempt to stop the kext.
6196 */
6197 if (startFlag) {
6198 /* Verify that the start/stop function is executable.
6199 */
6200 kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth,
6201 (vm_region_recurse_info_t)&info, &count);
6202 if (kern_result != KERN_SUCCESS) {
6203 OSKextLog(this,
6204 kOSKextLogErrorLevel |
6205 kOSKextLogLoadFlag,
6206 "Kext %s - bad %s pointer %p.",
6207 getIdentifierCString(),
6208 whichOp, (void *)ml_static_unslide(address));
6209 result = kOSKextReturnBadData;
6210 goto finish;
6211 }
6212
6213 #if VM_MAPPED_KEXTS
6214 if (!(info.protection & VM_PROT_EXECUTE)) {
6215 OSKextLog(this,
6216 kOSKextLogErrorLevel |
6217 kOSKextLogLoadFlag,
6218 "Kext %s - memory region containing module %s function "
6219 "is not executable.",
6220 getIdentifierCString(), whichOp);
6221 result = kOSKextReturnBadData;
6222 goto finish;
6223 }
6224 #endif
6225
6226 /* Verify that the kext's segments are backed by physical memory.
6227 */
6228 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
6229 while (seg) {
6230 if (!verifySegmentMapping(seg)) {
6231 result = kOSKextReturnBadData;
6232 goto finish;
6233 }
6234
6235 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
6236 }
6237 }
6238
6239 result = kOSReturnSuccess;
6240 finish:
6241 return result;
6242 }
6243
6244 /*********************************************************************
6245 *********************************************************************/
6246 boolean_t
6247 OSKext::verifySegmentMapping(kernel_segment_command_t *seg)
6248 {
6249 mach_vm_address_t address = 0;
6250
6251 if (!segmentShouldBeWired(seg)) {
6252 return true;
6253 }
6254
6255 for (address = seg->vmaddr;
6256 address < round_page(seg->vmaddr + seg->vmsize);
6257 address += PAGE_SIZE) {
6258 if (!pmap_find_phys(kernel_pmap, (vm_offset_t)address)) {
6259 OSKextLog(this,
6260 kOSKextLogErrorLevel |
6261 kOSKextLogLoadFlag,
6262 "Kext %s - page %p is not backed by physical memory.",
6263 getIdentifierCString(),
6264 (void *)address);
6265 return false;
6266 }
6267 }
6268
6269 return true;
6270 }
6271
6272 /*********************************************************************
6273 *********************************************************************/
6274 static void
6275 OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code)
6276 {
6277 uint64_t stamp = 0;
6278 firehose_tracepoint_id_u trace_id;
6279 struct firehose_trace_uuid_info_s uuid_info_s;
6280 firehose_trace_uuid_info_t uuid_info = &uuid_info_s;
6281 size_t uuid_info_len = sizeof(struct firehose_trace_uuid_info_s);
6282 OSData *uuid_data;
6283
6284 stamp = firehose_tracepoint_time(firehose_activity_flags_default);
6285 trace_id.ftid_value = FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata, _firehose_tracepoint_type_metadata_kext, (firehose_tracepoint_flags_t)0, code);
6286
6287 uuid_data = aKext->copyTextUUID();
6288 if (uuid_data) {
6289 memcpy(uuid_info->ftui_uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_info->ftui_uuid));
6290 OSSafeReleaseNULL(uuid_data);
6291 }
6292
6293 uuid_info->ftui_size = size;
6294 uuid_info->ftui_address = ml_static_unslide(address);
6295
6296 firehose_trace_metadata(firehose_stream_metadata, trace_id, stamp, uuid_info, uuid_info_len);
6297 return;
6298 }
6299
6300 /*********************************************************************
6301 *********************************************************************/
6302 OSReturn
6303 OSKext::start(bool startDependenciesFlag)
6304 {
6305 OSReturn result = kOSReturnError;
6306 kern_return_t (* startfunc)(kmod_info_t *, void *);
6307 unsigned int i, count;
6308 void * kmodStartData = NULL;
6309
6310 if (isStarted() || isInterface() || isKernelComponent()) {
6311 result = kOSReturnSuccess;
6312 goto finish;
6313 }
6314
6315 if (!isLoaded()) {
6316 OSKextLog(this,
6317 kOSKextLogErrorLevel |
6318 kOSKextLogLoadFlag,
6319 "Attempt to start nonloaded kext %s.",
6320 getIdentifierCString());
6321 result = kOSKextReturnInvalidArgument;
6322 goto finish;
6323 }
6324
6325 if (!sLoadEnabled) {
6326 OSKextLog(this,
6327 kOSKextLogErrorLevel |
6328 kOSKextLogLoadFlag,
6329 "Kext loading is disabled (attempt to start kext %s).",
6330 getIdentifierCString());
6331 result = kOSKextReturnDisabled;
6332 goto finish;
6333 }
6334
6335 result = validateKextMapping(/* start? */ true);
6336 if (result != kOSReturnSuccess) {
6337 goto finish;
6338 }
6339
6340 startfunc = kmod_info->start;
6341
6342 count = getNumDependencies();
6343 for (i = 0; i < count; i++) {
6344 OSKext * dependency = OSDynamicCast(OSKext, dependencies->getObject(i));
6345 if (dependency == NULL) {
6346 OSKextLog(this,
6347 kOSKextLogErrorLevel |
6348 kOSKextLogLoadFlag,
6349 "Kext %s start - internal error, dependency disappeared.",
6350 getIdentifierCString());
6351 goto finish;
6352 }
6353 if (!dependency->isStarted()) {
6354 if (startDependenciesFlag) {
6355 OSReturn dependencyResult =
6356 dependency->start(startDependenciesFlag);
6357 if (dependencyResult != KERN_SUCCESS) {
6358 OSKextLog(this,
6359 kOSKextLogErrorLevel |
6360 kOSKextLogLoadFlag,
6361 "Kext %s start - dependency %s failed to start (error 0x%x).",
6362 getIdentifierCString(),
6363 dependency->getIdentifierCString(),
6364 dependencyResult);
6365 goto finish;
6366 }
6367 } else {
6368 OSKextLog(this,
6369 kOSKextLogErrorLevel |
6370 kOSKextLogLoadFlag,
6371 "Not starting %s - dependency %s not started yet.",
6372 getIdentifierCString(),
6373 dependency->getIdentifierCString());
6374 result = kOSKextReturnStartStopError; // xxx - make new return?
6375 goto finish;
6376 }
6377 }
6378 }
6379
6380 OSKextLog(this,
6381 kOSKextLogDetailLevel |
6382 kOSKextLogLoadFlag,
6383 "Kext %s calling module start function.",
6384 getIdentifierCString());
6385
6386 flags.starting = 1;
6387
6388 // Drop a log message so logd can grab the needed information to decode this kext
6389 OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_load);
6390 result = OSRuntimeInitializeCPP(this);
6391 if (result == KERN_SUCCESS) {
6392 result = startfunc(kmod_info, kmodStartData);
6393 }
6394
6395 flags.starting = 0;
6396
6397 /* On success overlap the setting of started/starting. On failure just
6398 * clear starting.
6399 */
6400 if (result == KERN_SUCCESS) {
6401 flags.started = 1;
6402
6403 // xxx - log start error from kernel?
6404 OSKextLog(this,
6405 kOSKextLogProgressLevel |
6406 kOSKextLogLoadFlag,
6407 "Kext %s is now started.",
6408 getIdentifierCString());
6409 } else {
6410 invokeOrCancelRequestCallbacks(
6411 /* result not actually used */ kOSKextReturnStartStopError,
6412 /* invokeFlag */ false);
6413 OSKextLog(this,
6414 kOSKextLogProgressLevel |
6415 kOSKextLogLoadFlag,
6416 "Kext %s did not start (return code 0x%x).",
6417 getIdentifierCString(), result);
6418 }
6419
6420 finish:
6421 return result;
6422 }
6423
6424 /*********************************************************************
6425 *********************************************************************/
6426 /* static */
6427 bool
6428 OSKext::canUnloadKextWithIdentifier(
6429 OSString * kextIdentifier,
6430 bool checkClassesFlag)
6431 {
6432 bool result = false;
6433 OSKext * aKext = NULL;// do not release
6434
6435 IORecursiveLockLock(sKextLock);
6436
6437 aKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
6438
6439 if (!aKext) {
6440 goto finish; // can't unload what's not loaded
6441 }
6442
6443 if (aKext->isLoaded()) {
6444 if (aKext->getRetainCount() > kOSKextMinLoadedRetainCount) {
6445 goto finish;
6446 }
6447 if (checkClassesFlag && aKext->hasOSMetaClassInstances()) {
6448 goto finish;
6449 }
6450 }
6451
6452 result = true;
6453
6454 finish:
6455 IORecursiveLockUnlock(sKextLock);
6456 return result;
6457 }
6458
6459 /*********************************************************************
6460 *********************************************************************/
6461 OSReturn
6462 OSKext::stop(void)
6463 {
6464 OSReturn result = kOSReturnError;
6465 kern_return_t (*stopfunc)(kmod_info_t *, void *);
6466
6467 if (!isStarted() || isInterface()) {
6468 result = kOSReturnSuccess;
6469 goto finish;
6470 }
6471
6472 if (!isLoaded()) {
6473 OSKextLog(this,
6474 kOSKextLogErrorLevel |
6475 kOSKextLogLoadFlag,
6476 "Attempt to stop nonloaded kext %s.",
6477 getIdentifierCString());
6478 result = kOSKextReturnInvalidArgument;
6479 goto finish;
6480 }
6481
6482 /* Refuse to stop if we have clients or instances. It is up to
6483 * the caller to make sure those aren't true.
6484 */
6485 if (getRetainCount() > kOSKextMinLoadedRetainCount) {
6486 OSKextLog(this,
6487 kOSKextLogErrorLevel |
6488 kOSKextLogLoadFlag,
6489 "Kext %s - C++ instances; can't stop.",
6490 getIdentifierCString());
6491 result = kOSKextReturnInUse;
6492 goto finish;
6493 }
6494
6495 if (getRetainCount() > kOSKextMinLoadedRetainCount) {
6496 OSKextLog(this,
6497 kOSKextLogErrorLevel |
6498 kOSKextLogLoadFlag,
6499 "Kext %s - has references (linkage or tracking object); "
6500 "can't stop.",
6501 getIdentifierCString());
6502 result = kOSKextReturnInUse;
6503 goto finish;
6504 }
6505
6506 /* Note: If validateKextMapping fails on the stop & unload path,
6507 * we are in serious trouble and a kernel panic is likely whether
6508 * we stop & unload the kext or not.
6509 */
6510 result = validateKextMapping(/* start? */ false);
6511 if (result != kOSReturnSuccess) {
6512 goto finish;
6513 }
6514
6515 stopfunc = kmod_info->stop;
6516 if (stopfunc) {
6517 OSKextLog(this,
6518 kOSKextLogDetailLevel |
6519 kOSKextLogLoadFlag,
6520 "Kext %s calling module stop function.",
6521 getIdentifierCString());
6522
6523 flags.stopping = 1;
6524
6525 result = stopfunc(kmod_info, /* userData */ NULL);
6526 if (result == KERN_SUCCESS) {
6527 result = OSRuntimeFinalizeCPP(this);
6528 }
6529
6530 flags.stopping = 0;
6531
6532 if (result == KERN_SUCCESS) {
6533 flags.started = 0;
6534
6535 OSKextLog(this,
6536 kOSKextLogDetailLevel |
6537 kOSKextLogLoadFlag,
6538 "Kext %s is now stopped and ready to unload.",
6539 getIdentifierCString());
6540 } else {
6541 OSKextLog(this,
6542 kOSKextLogErrorLevel |
6543 kOSKextLogLoadFlag,
6544 "Kext %s did not stop (return code 0x%x).",
6545 getIdentifierCString(), result);
6546 result = kOSKextReturnStartStopError;
6547 }
6548 }
6549
6550 finish:
6551 // Drop a log message so logd can update this kext's metadata
6552 OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_unload);
6553 return result;
6554 }
6555
6556 /*********************************************************************
6557 *********************************************************************/
6558 OSReturn
6559 OSKext::unload(void)
6560 {
6561 OSReturn result = kOSReturnError;
6562 unsigned int index;
6563 uint32_t num_kmod_refs = 0;
6564 OSKextAccount * freeAccount;
6565
6566 if (!sUnloadEnabled) {
6567 OSKextLog(this,
6568 kOSKextLogErrorLevel |
6569 kOSKextLogLoadFlag,
6570 "Kext unloading is disabled (%s).",
6571 this->getIdentifierCString());
6572
6573 result = kOSKextReturnDisabled;
6574 goto finish;
6575 }
6576
6577 /* Refuse to unload if we have clients or instances. It is up to
6578 * the caller to make sure those aren't true.
6579 */
6580 if (getRetainCount() > kOSKextMinLoadedRetainCount) {
6581 // xxx - Don't log under errors? this is more of an info thing
6582 OSKextLog(this,
6583 kOSKextLogErrorLevel |
6584 kOSKextLogKextBookkeepingFlag,
6585 "Can't unload kext %s; outstanding references (linkage or tracking object).",
6586 getIdentifierCString());
6587 result = kOSKextReturnInUse;
6588 goto finish;
6589 }
6590
6591 if (!isLoaded()) {
6592 result = kOSReturnSuccess;
6593 goto finish;
6594 }
6595
6596 if (isKernelComponent()) {
6597 result = kOSKextReturnInvalidArgument;
6598 goto finish;
6599 }
6600
6601 if (metaClasses && !OSMetaClass::removeClasses(metaClasses)) {
6602 OSKextLog(this,
6603 kOSKextLogErrorLevel |
6604 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
6605 "Can't unload kext %s; classes have instances:",
6606 getIdentifierCString());
6607 reportOSMetaClassInstances(kOSKextLogErrorLevel |
6608 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag);
6609 result = kOSKextReturnInUse;
6610 goto finish;
6611 }
6612
6613 /* Note that the kext is unloading before running any code that
6614 * might be in the kext (request callbacks, module stop function).
6615 * We will deny certain requests made against a kext in the process
6616 * of unloading.
6617 */
6618 flags.unloading = 1;
6619
6620 /* Update the string describing the last kext to unload in case we panic.
6621 */
6622 savePanicString(/* isLoading */ false);
6623
6624 if (isStarted()) {
6625 result = stop();
6626 if (result != KERN_SUCCESS) {
6627 OSKextLog(this,
6628 kOSKextLogErrorLevel |
6629 kOSKextLogLoadFlag,
6630 "Kext %s can't unload - module stop returned 0x%x.",
6631 getIdentifierCString(), (unsigned)result);
6632 result = kOSKextReturnStartStopError;
6633 goto finish;
6634 }
6635 }
6636
6637 OSKextLog(this,
6638 kOSKextLogProgressLevel |
6639 kOSKextLogLoadFlag,
6640 "Kext %s unloading.",
6641 getIdentifierCString());
6642
6643 {
6644 struct list_head *p;
6645 struct list_head *prev;
6646 struct list_head *next;
6647 for (p = pendingPgoHead.next; p != &pendingPgoHead; p = next) {
6648 OSKextGrabPgoStruct *s = container_of(p, OSKextGrabPgoStruct, list_head);
6649 s->err = OSKextGrabPgoDataLocked(this, s->metadata, instance_uuid, s->pSize, s->pBuffer, s->bufferSize);
6650 prev = p->prev;
6651 next = p->next;
6652 prev->next = next;
6653 next->prev = prev;
6654 p->prev = p;
6655 p->next = p;
6656 IORecursiveLockWakeup(sKextLock, s, false);
6657 }
6658 }
6659
6660
6661 /* Even if we don't call the stop function, we want to be sure we
6662 * have no OSMetaClass references before unloading the kext executable
6663 * from memory. OSMetaClasses may have pointers into the kext executable
6664 * and that would cause a panic on OSKext::free() when metaClasses is freed.
6665 */
6666 if (metaClasses) {
6667 metaClasses->flushCollection();
6668 }
6669 (void) OSRuntimeFinalizeCPP(this);
6670
6671 /* Remove the kext from the list of loaded kexts, patch the gap
6672 * in the kmod_info_t linked list, and reset "kmod" to point to the
6673 * last loaded kext that isn't the fake kernel kext (sKernelKext).
6674 */
6675 index = sLoadedKexts->getNextIndexOfObject(this, 0);
6676 if (index != (unsigned int)-1) {
6677 sLoadedKexts->removeObject(index);
6678
6679 OSKext * nextKext = OSDynamicCast(OSKext,
6680 sLoadedKexts->getObject(index));
6681
6682 if (nextKext) {
6683 if (index > 0) {
6684 OSKext * gapKext = OSDynamicCast(OSKext,
6685 sLoadedKexts->getObject(index - 1));
6686
6687 nextKext->kmod_info->next = gapKext->kmod_info;
6688 } else { /* index == 0 */
6689 nextKext->kmod_info->next = NULL;
6690 }
6691 }
6692
6693 OSKext * lastKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
6694 if (lastKext && !lastKext->isKernel()) {
6695 kmod = lastKext->kmod_info;
6696 } else {
6697 kmod = NULL; // clear the global kmod variable
6698 }
6699 }
6700
6701 /* Clear out the kmod references that we're keeping for compatibility
6702 * with current panic backtrace code & kgmacros.
6703 * xxx - will want to update those bits sometime and remove this.
6704 */
6705 num_kmod_refs = getNumDependencies();
6706 if (num_kmod_refs && kmod_info && kmod_info->reference_list) {
6707 for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
6708 kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
6709 ref->info->reference_count--;
6710 }
6711 kfree(kmod_info->reference_list,
6712 num_kmod_refs * sizeof(kmod_reference_t));
6713 }
6714
6715 #if CONFIG_DTRACE
6716 unregisterWithDTrace();
6717 #endif /* CONFIG_DTRACE */
6718
6719 notifyKextUnloadObservers(this);
6720
6721 freeAccount = NULL;
6722 IOSimpleLockLock(sKextAccountsLock);
6723 account->kext = NULL;
6724 if (account->site.tag) {
6725 account->site.flags |= VM_TAG_UNLOAD;
6726 } else {
6727 freeAccount = account;
6728 }
6729 IOSimpleLockUnlock(sKextAccountsLock);
6730 if (freeAccount) {
6731 IODelete(freeAccount, OSKextAccount, 1);
6732 }
6733
6734 /* Unwire and free the linked executable.
6735 */
6736 if (linkedExecutable) {
6737 #if KASAN
6738 kasan_unload_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(), linkedExecutable->getLength());
6739 #endif
6740
6741 #if VM_MAPPED_KEXTS
6742 if (!isInterface()) {
6743 kernel_segment_command_t *seg = NULL;
6744 vm_map_t kext_map = kext_get_vm_map(kmod_info);
6745
6746 if (!kext_map) {
6747 OSKextLog(this,
6748 kOSKextLogErrorLevel |
6749 kOSKextLogLoadFlag,
6750 "Failed to free kext %s; couldn't find the kext map.",
6751 getIdentifierCString());
6752 result = kOSKextReturnInternalError;
6753 goto finish;
6754 }
6755
6756 OSKextLog(this,
6757 kOSKextLogProgressLevel |
6758 kOSKextLogLoadFlag,
6759 "Kext %s unwiring and unmapping linked executable.",
6760 getIdentifierCString());
6761
6762 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
6763 while (seg) {
6764 if (segmentShouldBeWired(seg)) {
6765 result = vm_map_unwire(kext_map, seg->vmaddr,
6766 seg->vmaddr + seg->vmsize, FALSE);
6767 if (result != KERN_SUCCESS) {
6768 OSKextLog(this,
6769 kOSKextLogErrorLevel |
6770 kOSKextLogLoadFlag,
6771 "Failed to unwire kext %s.",
6772 getIdentifierCString());
6773 result = kOSKextReturnInternalError;
6774 goto finish;
6775 }
6776 }
6777
6778 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
6779 }
6780 }
6781 #endif
6782 OSSafeReleaseNULL(linkedExecutable);
6783 }
6784
6785 /* An interface kext has a fake kmod_info that was allocated,
6786 * so we have to free it.
6787 */
6788 if (isInterface()) {
6789 kfree(kmod_info, sizeof(kmod_info_t));
6790 }
6791
6792 kmod_info = NULL;
6793
6794 flags.loaded = false;
6795 flushDependencies();
6796
6797 /* save a copy of the bundle ID for us to check when deciding to
6798 * rebuild the kernel cache file. If a kext was already in the kernel
6799 * cache and unloaded then later loaded we do not need to rebuild the
6800 * kernel cache. 9055303
6801 */
6802 if (isPrelinked()) {
6803 if (!_OSKextInUnloadedPrelinkedKexts(bundleID)) {
6804 IORecursiveLockLock(sKextLock);
6805 if (sUnloadedPrelinkedKexts) {
6806 sUnloadedPrelinkedKexts->setObject(bundleID);
6807 }
6808 IORecursiveLockUnlock(sKextLock);
6809 }
6810 }
6811
6812 OSKextLog(this,
6813 kOSKextLogProgressLevel | kOSKextLogLoadFlag,
6814 "Kext %s unloaded.", getIdentifierCString());
6815
6816 queueKextNotification(kKextRequestPredicateUnloadNotification,
6817 OSDynamicCast(OSString, bundleID));
6818
6819 finish:
6820 OSKext::saveLoadedKextPanicList();
6821 OSKext::updateLoadedKextSummaries();
6822
6823 flags.unloading = 0;
6824 return result;
6825 }
6826
6827 /*********************************************************************
6828 * Assumes sKextLock is held.
6829 *********************************************************************/
6830 /* static */
6831 OSReturn
6832 OSKext::queueKextNotification(
6833 const char * notificationName,
6834 OSString * kextIdentifier)
6835 {
6836 OSReturn result = kOSReturnError;
6837 OSDictionary * loadRequest = NULL;// must release
6838
6839 if (!kextIdentifier) {
6840 result = kOSKextReturnInvalidArgument;
6841 goto finish;
6842 }
6843
6844 /* Create a new request unless one is already sitting
6845 * in sKernelRequests for this bundle identifier
6846 */
6847 result = _OSKextCreateRequest(notificationName, &loadRequest);
6848 if (result != kOSReturnSuccess) {
6849 goto finish;
6850 }
6851 if (!_OSKextSetRequestArgument(loadRequest,
6852 kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
6853 result = kOSKextReturnNoMemory;
6854 goto finish;
6855 }
6856 if (!sKernelRequests->setObject(loadRequest)) {
6857 result = kOSKextReturnNoMemory;
6858 goto finish;
6859 }
6860
6861 /* We might want to only queue the notification if kextd is active,
6862 * but that wouldn't work for embedded. Note that we don't care if
6863 * the ping immediately succeeds here so don't do anything with the
6864 * result of this call.
6865 */
6866 OSKext::pingKextd();
6867
6868 result = kOSReturnSuccess;
6869
6870 finish:
6871 OSSafeReleaseNULL(loadRequest);
6872
6873 return result;
6874 }
6875
6876 /*********************************************************************
6877 *********************************************************************/
6878 static void
6879 _OSKextConsiderDestroyingLinkContext(
6880 __unused thread_call_param_t p0,
6881 __unused thread_call_param_t p1)
6882 {
6883 /* Take multiple locks in the correct order.
6884 */
6885 IORecursiveLockLock(sKextLock);
6886 IORecursiveLockLock(sKextInnerLock);
6887
6888 /* The first time we destroy the kxldContext is in the first
6889 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
6890 * before calling this function. Thereafter any call to this function
6891 * will actually destroy the context.
6892 */
6893 if (sConsiderUnloadsCalled && sKxldContext) {
6894 kxld_destroy_context(sKxldContext);
6895 sKxldContext = NULL;
6896 }
6897
6898 /* Free the thread_call that was allocated to execute this function.
6899 */
6900 if (sDestroyLinkContextThread) {
6901 if (!thread_call_free(sDestroyLinkContextThread)) {
6902 OSKextLog(/* kext */ NULL,
6903 kOSKextLogErrorLevel |
6904 kOSKextLogGeneralFlag,
6905 "thread_call_free() failed for kext link context.");
6906 }
6907 sDestroyLinkContextThread = 0;
6908 }
6909
6910 IORecursiveLockUnlock(sKextInnerLock);
6911 IORecursiveLockUnlock(sKextLock);
6912
6913 return;
6914 }
6915
6916 /*********************************************************************
6917 * Destroying the kxldContext requires checking variables under both
6918 * sKextInnerLock and sKextLock, so we do it on a separate thread
6919 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
6920 * call relationship.
6921 *
6922 * This function must be invoked with sKextInnerLock held.
6923 * Do not call any function that takes sKextLock here!
6924 *********************************************************************/
6925 /* static */
6926 void
6927 OSKext::considerDestroyingLinkContext(void)
6928 {
6929 IORecursiveLockLock(sKextInnerLock);
6930
6931 /* If we have already queued a thread to destroy the link context,
6932 * don't bother resetting; that thread will take care of it.
6933 */
6934 if (sDestroyLinkContextThread) {
6935 goto finish;
6936 }
6937
6938 /* The function to be invoked in the thread will deallocate
6939 * this thread_call, so don't share it around.
6940 */
6941 sDestroyLinkContextThread = thread_call_allocate(
6942 &_OSKextConsiderDestroyingLinkContext, 0);
6943 if (!sDestroyLinkContextThread) {
6944 OSKextLog(/* kext */ NULL,
6945 kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogLinkFlag,
6946 "Can't create thread to destroy kext link context.");
6947 goto finish;
6948 }
6949
6950 thread_call_enter(sDestroyLinkContextThread);
6951
6952 finish:
6953 IORecursiveLockUnlock(sKextInnerLock);
6954 return;
6955 }
6956
6957 #if PRAGMA_MARK
6958 #pragma mark Autounload
6959 #endif
6960 /*********************************************************************
6961 * This is a static method because the kext will be deallocated if it
6962 * does unload!
6963 *********************************************************************/
6964 /* static */
6965 OSReturn
6966 OSKext::autounloadKext(OSKext * aKext)
6967 {
6968 OSReturn result = kOSKextReturnInUse;
6969
6970 /* Check for external references to this kext (usu. dependents),
6971 * instances of defined classes (or classes derived from them),
6972 * outstanding requests.
6973 */
6974 if ((aKext->getRetainCount() > kOSKextMinLoadedRetainCount) ||
6975 !aKext->flags.autounloadEnabled ||
6976 aKext->isKernelComponent()) {
6977 goto finish;
6978 }
6979
6980 /* Skip a delay-autounload kext, once.
6981 */
6982 if (aKext->flags.delayAutounload) {
6983 OSKextLog(aKext,
6984 kOSKextLogProgressLevel |
6985 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
6986 "Kext %s has delayed autounload set; skipping and clearing flag.",
6987 aKext->getIdentifierCString());
6988 aKext->flags.delayAutounload = 0;
6989 goto finish;
6990 }
6991
6992 if (aKext->hasOSMetaClassInstances() ||
6993 aKext->countRequestCallbacks()) {
6994 goto finish;
6995 }
6996
6997 result = OSKext::removeKext(aKext);
6998
6999 finish:
7000 return result;
7001 }
7002
7003 /*********************************************************************
7004 *********************************************************************/
7005 void
7006 _OSKextConsiderUnloads(
7007 __unused thread_call_param_t p0,
7008 __unused thread_call_param_t p1)
7009 {
7010 bool didUnload = false;
7011 unsigned int count, i;
7012
7013 /* Take multiple locks in the correct order
7014 * (note also sKextSummaries lock further down).
7015 */
7016 IORecursiveLockLock(sKextLock);
7017 IORecursiveLockLock(sKextInnerLock);
7018
7019 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
7020
7021 /* If the system is powering down, don't try to unload anything.
7022 */
7023 if (sSystemSleep) {
7024 goto finish;
7025 }
7026
7027 OSKextLog(/* kext */ NULL,
7028 kOSKextLogProgressLevel | kOSKextLogLoadFlag,
7029 "Checking for unused kexts to autounload.");
7030
7031 /*****
7032 * Remove any request callbacks marked as stale,
7033 * and mark as stale any currently in flight.
7034 */
7035 count = sRequestCallbackRecords->getCount();
7036 if (count) {
7037 i = count - 1;
7038 do {
7039 OSDictionary * callbackRecord = OSDynamicCast(OSDictionary,
7040 sRequestCallbackRecords->getObject(i));
7041 OSBoolean * stale = OSDynamicCast(OSBoolean,
7042 callbackRecord->getObject(kKextRequestStaleKey));
7043
7044 if (stale == kOSBooleanTrue) {
7045 OSKext::invokeRequestCallback(callbackRecord,
7046 kOSKextReturnTimeout);
7047 } else {
7048 callbackRecord->setObject(kKextRequestStaleKey,
7049 kOSBooleanTrue);
7050 }
7051 } while (i--);
7052 }
7053
7054 /*****
7055 * Make multiple passes through the array of loaded kexts until
7056 * we don't unload any. This handles unwinding of dependency
7057 * chains. We have to go *backwards* through the array because
7058 * kexts are removed from it when unloaded, and we cannot make
7059 * a copy or we'll mess up the retain counts we rely on to
7060 * check whether a kext will unload. If only we could have
7061 * nonretaining collections like CF has....
7062 */
7063 do {
7064 didUnload = false;
7065
7066 count = sLoadedKexts->getCount();
7067 if (count) {
7068 i = count - 1;
7069 do {
7070 OSKext * thisKext = OSDynamicCast(OSKext,
7071 sLoadedKexts->getObject(i));
7072 didUnload |= (kOSReturnSuccess == OSKext::autounloadKext(thisKext));
7073 } while (i--);
7074 }
7075 } while (didUnload);
7076
7077 finish:
7078 sConsiderUnloadsPending = false;
7079 sConsiderUnloadsExecuted = true;
7080
7081 (void) OSKext::considerRebuildOfPrelinkedKernel();
7082
7083 IORecursiveLockUnlock(sKextInnerLock);
7084 IORecursiveLockUnlock(sKextLock);
7085
7086 return;
7087 }
7088
7089 /*********************************************************************
7090 * Do not call any function that takes sKextLock here!
7091 *********************************************************************/
7092 void
7093 OSKext::considerUnloads(Boolean rescheduleOnlyFlag)
7094 {
7095 AbsoluteTime when;
7096
7097 IORecursiveLockLock(sKextInnerLock);
7098
7099 if (!sUnloadCallout) {
7100 sUnloadCallout = thread_call_allocate(&_OSKextConsiderUnloads, 0);
7101 }
7102
7103 /* we only reset delay value for unloading if we already have something
7104 * pending. rescheduleOnlyFlag should not start the count down.
7105 */
7106 if (rescheduleOnlyFlag && !sConsiderUnloadsPending) {
7107 goto finish;
7108 }
7109
7110 thread_call_cancel(sUnloadCallout);
7111 if (OSKext::getAutounloadEnabled() && !sSystemSleep) {
7112 clock_interval_to_deadline(sConsiderUnloadDelay,
7113 1000 * 1000 * 1000, &when);
7114
7115 OSKextLog(/* kext */ NULL,
7116 kOSKextLogProgressLevel |
7117 kOSKextLogLoadFlag,
7118 "%scheduling %sscan for unused kexts in %lu seconds.",
7119 sConsiderUnloadsPending ? "Res" : "S",
7120 sConsiderUnloadsCalled ? "" : "initial ",
7121 (unsigned long)sConsiderUnloadDelay);
7122
7123 sConsiderUnloadsPending = true;
7124 thread_call_enter_delayed(sUnloadCallout, when);
7125 }
7126
7127 finish:
7128 /* The kxld context should be reused throughout boot. We mark the end of
7129 * period as the first time considerUnloads() is called, and we destroy
7130 * the first kxld context in that function. Afterwards, it will be
7131 * destroyed in flushNonloadedKexts.
7132 */
7133 if (!sConsiderUnloadsCalled) {
7134 sConsiderUnloadsCalled = true;
7135 OSKext::considerDestroyingLinkContext();
7136 }
7137
7138 IORecursiveLockUnlock(sKextInnerLock);
7139 return;
7140 }
7141
7142 /*********************************************************************
7143 * Do not call any function that takes sKextLock here!
7144 *********************************************************************/
7145 extern "C" {
7146 IOReturn OSKextSystemSleepOrWake(UInt32 messageType);
7147 IOReturn
7148 OSKextSystemSleepOrWake(UInt32 messageType)
7149 {
7150 IORecursiveLockLock(sKextInnerLock);
7151
7152 /* If the system is going to sleep, cancel the reaper thread timer,
7153 * and note that we're in a sleep state in case it just fired but hasn't
7154 * taken the lock yet. If we are coming back from sleep, just
7155 * clear the sleep flag; IOService's normal operation will cause
7156 * unloads to be considered soon enough.
7157 */
7158 if (messageType == kIOMessageSystemWillSleep) {
7159 if (sUnloadCallout) {
7160 thread_call_cancel(sUnloadCallout);
7161 }
7162 sSystemSleep = true;
7163 AbsoluteTime_to_scalar(&sLastWakeTime) = 0;
7164 } else if (messageType == kIOMessageSystemHasPoweredOn) {
7165 sSystemSleep = false;
7166 clock_get_uptime(&sLastWakeTime);
7167 }
7168 IORecursiveLockUnlock(sKextInnerLock);
7169
7170 return kIOReturnSuccess;
7171 }
7172 };
7173
7174
7175 #if PRAGMA_MARK
7176 #pragma mark Prelinked Kernel
7177 #endif
7178 /*********************************************************************
7179 * Do not access sConsiderUnloads... variables other than
7180 * sConsiderUnloadsExecuted in this function. They are guarded by a
7181 * different lock.
7182 *********************************************************************/
7183 /* static */
7184 void
7185 OSKext::considerRebuildOfPrelinkedKernel(void)
7186 {
7187 static bool requestedPrelink = false;
7188 OSReturn checkResult = kOSReturnError;
7189 OSDictionary * prelinkRequest = NULL;// must release
7190 OSCollectionIterator * kextIterator = NULL;// must release
7191 const OSSymbol * thisID = NULL;// do not release
7192 bool doRebuild = false;
7193 AbsoluteTime my_abstime;
7194 UInt64 my_ns;
7195 SInt32 delta_secs;
7196
7197 /* Only one auto rebuild per boot and only on boot from prelinked kernel */
7198 if (requestedPrelink || !sPrelinkBoot) {
7199 return;
7200 }
7201
7202 /* no direct return from this point */
7203 IORecursiveLockLock(sKextLock);
7204
7205 /* We need to wait for kextd to get up and running with unloads already done
7206 * and any new startup kexts loaded.
7207 */
7208 if (!sConsiderUnloadsExecuted ||
7209 !sDeferredLoadSucceeded) {
7210 goto finish;
7211 }
7212
7213 /* we really only care about boot / system start up related kexts so bail
7214 * if we're here after REBUILD_MAX_TIME.
7215 */
7216 if (!_OSKextInPrelinkRebuildWindow()) {
7217 OSKextLog(/* kext */ NULL,
7218 kOSKextLogArchiveFlag,
7219 "%s prebuild rebuild has expired",
7220 __FUNCTION__);
7221 requestedPrelink = true;
7222 goto finish;
7223 }
7224
7225 /* we do not want to trigger a rebuild if we get here too close to waking
7226 * up. (see radar 10233768)
7227 */
7228 IORecursiveLockLock(sKextInnerLock);
7229
7230 clock_get_uptime(&my_abstime);
7231 delta_secs = MINIMUM_WAKEUP_SECONDS + 1;
7232 if (AbsoluteTime_to_scalar(&sLastWakeTime) != 0) {
7233 SUB_ABSOLUTETIME(&my_abstime, &sLastWakeTime);
7234 absolutetime_to_nanoseconds(my_abstime, &my_ns);
7235 delta_secs = (SInt32)(my_ns / NSEC_PER_SEC);
7236 }
7237 IORecursiveLockUnlock(sKextInnerLock);
7238
7239 if (delta_secs < MINIMUM_WAKEUP_SECONDS) {
7240 /* too close to time of last wake from sleep */
7241 goto finish;
7242 }
7243 requestedPrelink = true;
7244
7245 /* Now it's time to see if we have a reason to rebuild. We may have done
7246 * some loads and unloads but the kernel cache didn't actually change.
7247 * We will rebuild if any kext is not marked prelinked AND is not in our
7248 * list of prelinked kexts that got unloaded. (see radar 9055303)
7249 */
7250 kextIterator = OSCollectionIterator::withCollection(sKextsByID);
7251 if (!kextIterator) {
7252 goto finish;
7253 }
7254
7255 while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
7256 OSKext * thisKext;// do not release
7257
7258 thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
7259 if (!thisKext || thisKext->isPrelinked() || thisKext->isKernel()) {
7260 continue;
7261 }
7262
7263 if (_OSKextInUnloadedPrelinkedKexts(thisKext->bundleID)) {
7264 continue;
7265 }
7266 /* kext is loaded and was not in current kernel cache so let's rebuild
7267 */
7268 doRebuild = true;
7269 OSKextLog(/* kext */ NULL,
7270 kOSKextLogArchiveFlag,
7271 "considerRebuildOfPrelinkedKernel %s triggered rebuild",
7272 thisKext->bundleID->getCStringNoCopy());
7273 break;
7274 }
7275 sUnloadedPrelinkedKexts->flushCollection();
7276
7277 if (!doRebuild) {
7278 goto finish;
7279 }
7280
7281 checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestPrelink,
7282 &prelinkRequest);
7283 if (checkResult != kOSReturnSuccess) {
7284 goto finish;
7285 }
7286
7287 if (!sKernelRequests->setObject(prelinkRequest)) {
7288 goto finish;
7289 }
7290
7291 OSKext::pingKextd();
7292
7293 finish:
7294 IORecursiveLockUnlock(sKextLock);
7295 OSSafeReleaseNULL(prelinkRequest);
7296 OSSafeReleaseNULL(kextIterator);
7297
7298 return;
7299 }
7300
7301 #if PRAGMA_MARK
7302 #pragma mark Dependencies
7303 #endif
7304 /*********************************************************************
7305 *********************************************************************/
7306 bool
7307 OSKext::resolveDependencies(
7308 OSArray * loopStack)
7309 {
7310 bool result = false;
7311 OSArray * localLoopStack = NULL;// must release
7312 bool addedToLoopStack = false;
7313 OSDictionary * libraries = NULL;// do not release
7314 OSCollectionIterator * libraryIterator = NULL;// must release
7315 OSString * libraryID = NULL;// do not release
7316 OSString * infoString = NULL;// do not release
7317 OSString * readableString = NULL;// do not release
7318 OSKext * libraryKext = NULL;// do not release
7319 bool hasRawKernelDependency = false;
7320 bool hasKernelDependency = false;
7321 bool hasKPIDependency = false;
7322 bool hasPrivateKPIDependency = false;
7323 unsigned int count;
7324
7325 /* A kernel component will automatically have this flag set,
7326 * and a loaded kext should also have it set (as should all its
7327 * loaded dependencies).
7328 */
7329 if (flags.hasAllDependencies) {
7330 result = true;
7331 goto finish;
7332 }
7333
7334 /* Check for loops in the dependency graph.
7335 */
7336 if (loopStack) {
7337 if (loopStack->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
7338 OSKextLog(this,
7339 kOSKextLogErrorLevel |
7340 kOSKextLogDependenciesFlag,
7341 "Kext %s has a dependency loop; can't resolve dependencies.",
7342 getIdentifierCString());
7343 goto finish;
7344 }
7345 } else {
7346 OSKextLog(this,
7347 kOSKextLogStepLevel |
7348 kOSKextLogDependenciesFlag,
7349 "Kext %s resolving dependencies.",
7350 getIdentifierCString());
7351
7352 loopStack = OSArray::withCapacity(6); // any small capacity will do
7353 if (!loopStack) {
7354 OSKextLog(this,
7355 kOSKextLogErrorLevel |
7356 kOSKextLogDependenciesFlag,
7357 "Kext %s can't create bookkeeping stack to resolve dependencies.",
7358 getIdentifierCString());
7359 goto finish;
7360 }
7361 localLoopStack = loopStack;
7362 }
7363 if (!loopStack->setObject(this)) {
7364 OSKextLog(this,
7365 kOSKextLogErrorLevel |
7366 kOSKextLogDependenciesFlag,
7367 "Kext %s - internal error resolving dependencies.",
7368 getIdentifierCString());
7369 goto finish;
7370 }
7371 addedToLoopStack = true;
7372
7373 /* Purge any existing kexts in the dependency list and start over.
7374 */
7375 flushDependencies();
7376 if (dependencies) {
7377 OSKextLog(this,
7378 kOSKextLogErrorLevel |
7379 kOSKextLogDependenciesFlag,
7380 "Kext %s - internal error resolving dependencies.",
7381 getIdentifierCString());
7382 }
7383
7384 libraries = OSDynamicCast(OSDictionary,
7385 getPropertyForHostArch(kOSBundleLibrariesKey));
7386 if (libraries == NULL || libraries->getCount() == 0) {
7387 OSKextLog(this,
7388 kOSKextLogErrorLevel |
7389 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7390 "Kext %s - can't resolve dependencies; %s missing/invalid type.",
7391 getIdentifierCString(), kOSBundleLibrariesKey);
7392 goto finish;
7393 }
7394
7395 /* Make a new array to hold the dependencies (flush freed the old one).
7396 */
7397 dependencies = OSArray::withCapacity(libraries->getCount());
7398 if (!dependencies) {
7399 OSKextLog(this,
7400 kOSKextLogErrorLevel |
7401 kOSKextLogDependenciesFlag,
7402 "Kext %s - can't allocate dependencies array.",
7403 getIdentifierCString());
7404 goto finish;
7405 }
7406
7407 // xxx - compat: We used to add an implicit dependency on kernel 6.0
7408 // xxx - compat: if none were declared.
7409
7410 libraryIterator = OSCollectionIterator::withCollection(libraries);
7411 if (!libraryIterator) {
7412 OSKextLog(this,
7413 kOSKextLogErrorLevel |
7414 kOSKextLogDependenciesFlag,
7415 "Kext %s - can't allocate dependencies iterator.",
7416 getIdentifierCString());
7417 goto finish;
7418 }
7419
7420 while ((libraryID = OSDynamicCast(OSString,
7421 libraryIterator->getNextObject()))) {
7422 const char * library_id = libraryID->getCStringNoCopy();
7423
7424 OSString * libraryVersion = OSDynamicCast(OSString,
7425 libraries->getObject(libraryID));
7426 if (libraryVersion == NULL) {
7427 OSKextLog(this,
7428 kOSKextLogErrorLevel |
7429 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7430 "Kext %s - illegal type in OSBundleLibraries.",
7431 getIdentifierCString());
7432 goto finish;
7433 }
7434
7435 OSKextVersion libraryVers =
7436 OSKextParseVersionString(libraryVersion->getCStringNoCopy());
7437 if (libraryVers == -1) {
7438 OSKextLog(this,
7439 kOSKextLogErrorLevel |
7440 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7441 "Kext %s - invalid library version %s.",
7442 getIdentifierCString(),
7443 libraryVersion->getCStringNoCopy());
7444 goto finish;
7445 }
7446
7447 libraryKext = OSDynamicCast(OSKext, sKextsByID->getObject(libraryID));
7448 if (libraryKext == NULL) {
7449 OSKextLog(this,
7450 kOSKextLogErrorLevel |
7451 kOSKextLogDependenciesFlag,
7452 "Kext %s - library kext %s not found.",
7453 getIdentifierCString(), library_id);
7454 goto finish;
7455 }
7456
7457 if (!libraryKext->isCompatibleWithVersion(libraryVers)) {
7458 OSKextLog(this,
7459 kOSKextLogErrorLevel |
7460 kOSKextLogDependenciesFlag,
7461 "Kext %s - library kext %s not compatible "
7462 "with requested version %s.",
7463 getIdentifierCString(), library_id,
7464 libraryVersion->getCStringNoCopy());
7465 goto finish;
7466 }
7467
7468 /* If a nonprelinked library somehow got into the mix for a
7469 * prelinked kext, at any point in the chain, we must fail
7470 * because the prelinked relocs for the library will be all wrong.
7471 */
7472 if (this->isPrelinked() &&
7473 libraryKext->declaresExecutable() &&
7474 !libraryKext->isPrelinked()) {
7475 OSKextLog(this,
7476 kOSKextLogErrorLevel |
7477 kOSKextLogDependenciesFlag,
7478 "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
7479 getIdentifierCString(), library_id,
7480 libraryVersion->getCStringNoCopy());
7481 goto finish;
7482 }
7483
7484 if (!libraryKext->resolveDependencies(loopStack)) {
7485 goto finish;
7486 }
7487
7488 /* Add the library directly only if it has an executable to link.
7489 * Otherwise it's just used to collect other dependencies, so put
7490 * *its* dependencies on the list for this kext.
7491 */
7492 // xxx - We are losing info here; would like to make fake entries or
7493 // xxx - keep these in the dependency graph for loaded kexts.
7494 // xxx - I really want to make kernel components not a special case!
7495 if (libraryKext->declaresExecutable() ||
7496 libraryKext->isInterface()) {
7497 if (dependencies->getNextIndexOfObject(libraryKext, 0) == (unsigned)-1) {
7498 dependencies->setObject(libraryKext);
7499
7500 OSKextLog(this,
7501 kOSKextLogDetailLevel |
7502 kOSKextLogDependenciesFlag,
7503 "Kext %s added dependency %s.",
7504 getIdentifierCString(),
7505 libraryKext->getIdentifierCString());
7506 }
7507 } else {
7508 int numLibDependencies = libraryKext->getNumDependencies();
7509 OSArray * libraryDependencies = libraryKext->getDependencies();
7510 int index;
7511
7512 if (numLibDependencies) {
7513 // xxx - this msg level should be 1 lower than the per-kext one
7514 OSKextLog(this,
7515 kOSKextLogDetailLevel |
7516 kOSKextLogDependenciesFlag,
7517 "Kext %s pulling %d dependencies from codeless library %s.",
7518 getIdentifierCString(),
7519 numLibDependencies,
7520 libraryKext->getIdentifierCString());
7521 }
7522 for (index = 0; index < numLibDependencies; index++) {
7523 OSKext * thisLibDependency = OSDynamicCast(OSKext,
7524 libraryDependencies->getObject(index));
7525 if (dependencies->getNextIndexOfObject(thisLibDependency, 0) == (unsigned)-1) {
7526 dependencies->setObject(thisLibDependency);
7527 OSKextLog(this,
7528 kOSKextLogDetailLevel |
7529 kOSKextLogDependenciesFlag,
7530 "Kext %s added dependency %s from codeless library %s.",
7531 getIdentifierCString(),
7532 thisLibDependency->getIdentifierCString(),
7533 libraryKext->getIdentifierCString());
7534 }
7535 }
7536 }
7537
7538 if ((strlen(library_id) == strlen(KERNEL_LIB)) &&
7539 0 == strncmp(library_id, KERNEL_LIB, sizeof(KERNEL_LIB) - 1)) {
7540 hasRawKernelDependency = true;
7541 } else if (STRING_HAS_PREFIX(library_id, KERNEL_LIB_PREFIX)) {
7542 hasKernelDependency = true;
7543 } else if (STRING_HAS_PREFIX(library_id, KPI_LIB_PREFIX)) {
7544 hasKPIDependency = true;
7545 if (!strncmp(library_id, PRIVATE_KPI, sizeof(PRIVATE_KPI) - 1)) {
7546 hasPrivateKPIDependency = true;
7547 }
7548 }
7549 }
7550
7551 if (hasRawKernelDependency) {
7552 OSKextLog(this,
7553 kOSKextLogErrorLevel |
7554 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7555 "Error - kext %s declares a dependency on %s, which is not permitted.",
7556 getIdentifierCString(), KERNEL_LIB);
7557 goto finish;
7558 }
7559 #if __LP64__
7560 if (hasKernelDependency) {
7561 OSKextLog(this,
7562 kOSKextLogErrorLevel |
7563 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7564 "Error - kext %s declares %s dependencies. "
7565 "Only %s* dependencies are supported for 64-bit kexts.",
7566 getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
7567 goto finish;
7568 }
7569 if (!hasKPIDependency) {
7570 OSKextLog(this,
7571 kOSKextLogWarningLevel |
7572 kOSKextLogDependenciesFlag,
7573 "Warning - kext %s declares no %s* dependencies. "
7574 "If it uses any KPIs, the link may fail with undefined symbols.",
7575 getIdentifierCString(), KPI_LIB_PREFIX);
7576 }
7577 #else /* __LP64__ */
7578 // xxx - will change to flatly disallow "kernel" dependencies at some point
7579 // xxx - is it invalid to do both "com.apple.kernel" and any
7580 // xxx - "com.apple.kernel.*"?
7581
7582 if (hasKernelDependency && hasKPIDependency) {
7583 OSKextLog(this,
7584 kOSKextLogWarningLevel |
7585 kOSKextLogDependenciesFlag,
7586 "Warning - kext %s has immediate dependencies on both "
7587 "%s* and %s* components; use only one style.",
7588 getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
7589 }
7590
7591 if (!hasKernelDependency && !hasKPIDependency) {
7592 // xxx - do we want to use validation flag for these too?
7593 OSKextLog(this,
7594 kOSKextLogWarningLevel |
7595 kOSKextLogDependenciesFlag,
7596 "Warning - %s declares no kernel dependencies; using %s.",
7597 getIdentifierCString(), KERNEL6_LIB);
7598 OSKext * kernelKext = OSDynamicCast(OSKext,
7599 sKextsByID->getObject(KERNEL6_LIB));
7600 if (kernelKext) {
7601 dependencies->setObject(kernelKext);
7602 } else {
7603 OSKextLog(this,
7604 kOSKextLogErrorLevel |
7605 kOSKextLogDependenciesFlag,
7606 "Error - Library %s not found for %s.",
7607 KERNEL6_LIB, getIdentifierCString());
7608 }
7609 }
7610
7611 /* If the kext doesn't have a raw kernel or KPI dependency, then add all of
7612 * its indirect dependencies to simulate old-style linking. XXX - Should
7613 * check for duplicates.
7614 */
7615 if (!hasKPIDependency) {
7616 unsigned int i;
7617
7618 flags.hasBleedthrough = true;
7619
7620 count = getNumDependencies();
7621
7622 /* We add to the dependencies array in this loop, but do not iterate
7623 * past its original count.
7624 */
7625 for (i = 0; i < count; i++) {
7626 OSKext * dependencyKext = OSDynamicCast(OSKext,
7627 dependencies->getObject(i));
7628 dependencyKext->addBleedthroughDependencies(dependencies);
7629 }
7630 }
7631 #endif /* __LP64__ */
7632
7633 if (hasPrivateKPIDependency) {
7634 bool hasApplePrefix = false;
7635 bool infoCopyrightIsValid = false;
7636 bool readableCopyrightIsValid = false;
7637
7638 hasApplePrefix = STRING_HAS_PREFIX(getIdentifierCString(),
7639 APPLE_KEXT_PREFIX);
7640
7641 infoString = OSDynamicCast(OSString,
7642 getPropertyForHostArch("CFBundleGetInfoString"));
7643 if (infoString) {
7644 infoCopyrightIsValid =
7645 kxld_validate_copyright_string(infoString->getCStringNoCopy());
7646 }
7647
7648 readableString = OSDynamicCast(OSString,
7649 getPropertyForHostArch("NSHumanReadableCopyright"));
7650 if (readableString) {
7651 readableCopyrightIsValid =
7652 kxld_validate_copyright_string(readableString->getCStringNoCopy());
7653 }
7654
7655 if (!hasApplePrefix || (!infoCopyrightIsValid && !readableCopyrightIsValid)) {
7656 OSKextLog(this,
7657 kOSKextLogErrorLevel |
7658 kOSKextLogDependenciesFlag,
7659 "Error - kext %s declares a dependency on %s. "
7660 "Only Apple kexts may declare a dependency on %s.",
7661 getIdentifierCString(), PRIVATE_KPI, PRIVATE_KPI);
7662 goto finish;
7663 }
7664 }
7665
7666 result = true;
7667 flags.hasAllDependencies = 1;
7668
7669 finish:
7670
7671 if (addedToLoopStack) {
7672 count = loopStack->getCount();
7673 if (count > 0 && (this == loopStack->getObject(count - 1))) {
7674 loopStack->removeObject(count - 1);
7675 } else {
7676 OSKextLog(this,
7677 kOSKextLogErrorLevel |
7678 kOSKextLogDependenciesFlag,
7679 "Kext %s - internal error resolving dependencies.",
7680 getIdentifierCString());
7681 }
7682 }
7683
7684 if (result && localLoopStack) {
7685 OSKextLog(this,
7686 kOSKextLogStepLevel |
7687 kOSKextLogDependenciesFlag,
7688 "Kext %s successfully resolved dependencies.",
7689 getIdentifierCString());
7690 }
7691
7692 OSSafeReleaseNULL(localLoopStack);
7693 OSSafeReleaseNULL(libraryIterator);
7694
7695 return result;
7696 }
7697
7698 /*********************************************************************
7699 *********************************************************************/
7700 bool
7701 OSKext::addBleedthroughDependencies(OSArray * anArray)
7702 {
7703 bool result = false;
7704 unsigned int dependencyIndex, dependencyCount;
7705
7706 dependencyCount = getNumDependencies();
7707
7708 for (dependencyIndex = 0;
7709 dependencyIndex < dependencyCount;
7710 dependencyIndex++) {
7711 OSKext * dependency = OSDynamicCast(OSKext,
7712 dependencies->getObject(dependencyIndex));
7713 if (!dependency) {
7714 OSKextLog(this,
7715 kOSKextLogErrorLevel |
7716 kOSKextLogDependenciesFlag,
7717 "Kext %s - internal error propagating compatibility dependencies.",
7718 getIdentifierCString());
7719 goto finish;
7720 }
7721 if (anArray->getNextIndexOfObject(dependency, 0) == (unsigned int)-1) {
7722 anArray->setObject(dependency);
7723 }
7724 dependency->addBleedthroughDependencies(anArray);
7725 }
7726
7727 result = true;
7728
7729 finish:
7730 return result;
7731 }
7732
7733 /*********************************************************************
7734 *********************************************************************/
7735 bool
7736 OSKext::flushDependencies(bool forceFlag)
7737 {
7738 bool result = false;
7739
7740 /* Only clear the dependencies if the kext isn't loaded;
7741 * we need the info for loaded kexts to track references.
7742 */
7743 if (!isLoaded() || forceFlag) {
7744 if (dependencies) {
7745 // xxx - check level
7746 OSKextLog(this,
7747 kOSKextLogProgressLevel |
7748 kOSKextLogDependenciesFlag,
7749 "Kext %s flushing dependencies.",
7750 getIdentifierCString());
7751 OSSafeReleaseNULL(dependencies);
7752 }
7753 if (!isKernelComponent()) {
7754 flags.hasAllDependencies = 0;
7755 }
7756 result = true;
7757 }
7758
7759 return result;
7760 }
7761
7762 /*********************************************************************
7763 *********************************************************************/
7764 uint32_t
7765 OSKext::getNumDependencies(void)
7766 {
7767 if (!dependencies) {
7768 return 0;
7769 }
7770 return dependencies->getCount();
7771 }
7772
7773 /*********************************************************************
7774 *********************************************************************/
7775 OSArray *
7776 OSKext::getDependencies(void)
7777 {
7778 return dependencies;
7779 }
7780
7781 #if PRAGMA_MARK
7782 #pragma mark OSMetaClass Support
7783 #endif
7784 /*********************************************************************
7785 *********************************************************************/
7786 OSReturn
7787 OSKext::addClass(
7788 OSMetaClass * aClass,
7789 uint32_t numClasses)
7790 {
7791 OSReturn result = kOSMetaClassNoInsKModSet;
7792
7793 if (!metaClasses) {
7794 metaClasses = OSSet::withCapacity(numClasses);
7795 if (!metaClasses) {
7796 goto finish;
7797 }
7798 }
7799
7800 if (metaClasses->containsObject(aClass)) {
7801 OSKextLog(this,
7802 kOSKextLogWarningLevel |
7803 kOSKextLogLoadFlag,
7804 "Notice - kext %s has already registered class %s.",
7805 getIdentifierCString(),
7806 aClass->getClassName());
7807 result = kOSReturnSuccess;
7808 goto finish;
7809 }
7810
7811 if (!metaClasses->setObject(aClass)) {
7812 goto finish;
7813 } else {
7814 OSKextLog(this,
7815 kOSKextLogDetailLevel |
7816 kOSKextLogLoadFlag,
7817 "Kext %s registered class %s.",
7818 getIdentifierCString(),
7819 aClass->getClassName());
7820 }
7821
7822 if (!flags.autounloadEnabled) {
7823 const OSMetaClass * metaScan = NULL;// do not release
7824
7825 for (metaScan = aClass; metaScan; metaScan = metaScan->getSuperClass()) {
7826 if (metaScan == OSTypeID(IOService)) {
7827 OSKextLog(this,
7828 kOSKextLogProgressLevel |
7829 kOSKextLogLoadFlag,
7830 "Kext %s has IOService subclass %s; enabling autounload.",
7831 getIdentifierCString(),
7832 aClass->getClassName());
7833
7834 flags.autounloadEnabled = 1;
7835 break;
7836 }
7837 }
7838 }
7839
7840 notifyAddClassObservers(this, aClass, flags);
7841
7842 result = kOSReturnSuccess;
7843
7844 finish:
7845 if (result != kOSReturnSuccess) {
7846 OSKextLog(this,
7847 kOSKextLogErrorLevel |
7848 kOSKextLogLoadFlag,
7849 "Kext %s failed to register class %s.",
7850 getIdentifierCString(),
7851 aClass->getClassName());
7852 }
7853
7854 return result;
7855 }
7856
7857 /*********************************************************************
7858 *********************************************************************/
7859 OSReturn
7860 OSKext::removeClass(
7861 OSMetaClass * aClass)
7862 {
7863 OSReturn result = kOSMetaClassNoKModSet;
7864
7865 if (!metaClasses) {
7866 goto finish;
7867 }
7868
7869 if (!metaClasses->containsObject(aClass)) {
7870 OSKextLog(this,
7871 kOSKextLogWarningLevel |
7872 kOSKextLogLoadFlag,
7873 "Notice - kext %s asked to unregister unknown class %s.",
7874 getIdentifierCString(),
7875 aClass->getClassName());
7876 result = kOSReturnSuccess;
7877 goto finish;
7878 }
7879
7880 OSKextLog(this,
7881 kOSKextLogDetailLevel |
7882 kOSKextLogLoadFlag,
7883 "Kext %s unregistering class %s.",
7884 getIdentifierCString(),
7885 aClass->getClassName());
7886
7887 metaClasses->removeObject(aClass);
7888
7889 notifyRemoveClassObservers(this, aClass, flags);
7890
7891 result = kOSReturnSuccess;
7892
7893 finish:
7894 if (result != kOSReturnSuccess) {
7895 OSKextLog(this,
7896 kOSKextLogErrorLevel |
7897 kOSKextLogLoadFlag,
7898 "Failed to unregister kext %s class %s.",
7899 getIdentifierCString(),
7900 aClass->getClassName());
7901 }
7902 return result;
7903 }
7904
7905 /*********************************************************************
7906 *********************************************************************/
7907 OSSet *
7908 OSKext::getMetaClasses(void)
7909 {
7910 return metaClasses;
7911 }
7912
7913 /*********************************************************************
7914 *********************************************************************/
7915 bool
7916 OSKext::hasOSMetaClassInstances(void)
7917 {
7918 bool result = false;
7919 OSCollectionIterator * classIterator = NULL; // must release
7920 OSMetaClass * checkClass = NULL;// do not release
7921
7922 if (!metaClasses) {
7923 goto finish;
7924 }
7925
7926 classIterator = OSCollectionIterator::withCollection(metaClasses);
7927 if (!classIterator) {
7928 // xxx - log alloc failure?
7929 goto finish;
7930 }
7931 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
7932 if (checkClass->getInstanceCount()) {
7933 result = true;
7934 goto finish;
7935 }
7936 }
7937
7938 finish:
7939
7940 OSSafeReleaseNULL(classIterator);
7941 return result;
7942 }
7943
7944 /*********************************************************************
7945 *********************************************************************/
7946 /* static */
7947 void
7948 OSKext::reportOSMetaClassInstances(
7949 const char * kextIdentifier,
7950 OSKextLogSpec msgLogSpec)
7951 {
7952 OSKext * theKext = NULL; // must release
7953
7954 theKext = OSKext::lookupKextWithIdentifier(kextIdentifier);
7955 if (!theKext) {
7956 goto finish;
7957 }
7958
7959 theKext->reportOSMetaClassInstances(msgLogSpec);
7960 finish:
7961 OSSafeReleaseNULL(theKext);
7962 return;
7963 }
7964
7965 /*********************************************************************
7966 *********************************************************************/
7967 void
7968 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec)
7969 {
7970 OSCollectionIterator * classIterator = NULL; // must release
7971 OSMetaClass * checkClass = NULL;// do not release
7972
7973 if (!metaClasses) {
7974 goto finish;
7975 }
7976
7977 classIterator = OSCollectionIterator::withCollection(metaClasses);
7978 if (!classIterator) {
7979 goto finish;
7980 }
7981 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
7982 if (checkClass->getInstanceCount()) {
7983 OSKextLog(this,
7984 msgLogSpec,
7985 " Kext %s class %s has %d instance%s.",
7986 getIdentifierCString(),
7987 checkClass->getClassName(),
7988 checkClass->getInstanceCount(),
7989 checkClass->getInstanceCount() == 1 ? "" : "s");
7990 }
7991 }
7992
7993 finish:
7994 OSSafeReleaseNULL(classIterator);
7995 return;
7996 }
7997
7998 #if PRAGMA_MARK
7999 #pragma mark User-Space Requests
8000 #endif
8001 /*********************************************************************
8002 * XXX - this function is a big ugly mess
8003 *********************************************************************/
8004 /* static */
8005 OSReturn
8006 OSKext::handleRequest(
8007 host_priv_t hostPriv,
8008 OSKextLogSpec clientLogFilter,
8009 char * requestBuffer,
8010 uint32_t requestLength,
8011 char ** responseOut,
8012 uint32_t * responseLengthOut,
8013 char ** logInfoOut,
8014 uint32_t * logInfoLengthOut)
8015 {
8016 OSReturn result = kOSReturnError;
8017 kern_return_t kmem_result = KERN_FAILURE;
8018
8019 char * response = NULL;// returned by reference
8020 uint32_t responseLength = 0;
8021
8022 OSObject * parsedXML = NULL;// must release
8023 OSDictionary * requestDict = NULL;// do not release
8024 OSString * errorString = NULL;// must release
8025
8026 OSObject * responseObject = NULL;// must release
8027
8028 OSSerialize * serializer = NULL;// must release
8029
8030 OSArray * logInfoArray = NULL;// must release
8031
8032 OSString * predicate = NULL;// do not release
8033 OSString * kextIdentifier = NULL;// do not release
8034 OSArray * kextIdentifiers = NULL;// do not release
8035 OSKext * theKext = NULL;// do not release
8036 OSBoolean * boolArg = NULL;// do not release
8037
8038 IORecursiveLockLock(sKextLock);
8039
8040 if (responseOut) {
8041 *responseOut = NULL;
8042 *responseLengthOut = 0;
8043 }
8044 if (logInfoOut) {
8045 *logInfoOut = NULL;
8046 *logInfoLengthOut = 0;
8047 }
8048
8049 OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
8050
8051 /* XML must be nul-terminated.
8052 */
8053 if (requestBuffer[requestLength - 1] != '\0') {
8054 OSKextLog(/* kext */ NULL,
8055 kOSKextLogErrorLevel |
8056 kOSKextLogIPCFlag,
8057 "Invalid request from user space (not nul-terminated).");
8058 result = kOSKextReturnBadData;
8059 goto finish;
8060 }
8061 parsedXML = OSUnserializeXML((const char *)requestBuffer, &errorString);
8062 if (parsedXML) {
8063 requestDict = OSDynamicCast(OSDictionary, parsedXML);
8064 }
8065 if (!requestDict) {
8066 const char * errorCString = "(unknown error)";
8067
8068 if (errorString && errorString->getCStringNoCopy()) {
8069 errorCString = errorString->getCStringNoCopy();
8070 } else if (parsedXML) {
8071 errorCString = "not a dictionary";
8072 }
8073 OSKextLog(/* kext */ NULL,
8074 kOSKextLogErrorLevel |
8075 kOSKextLogIPCFlag,
8076 "Error unserializing request from user space: %s.",
8077 errorCString);
8078 result = kOSKextReturnSerialization;
8079 goto finish;
8080 }
8081
8082 predicate = _OSKextGetRequestPredicate(requestDict);
8083 if (!predicate) {
8084 OSKextLog(/* kext */ NULL,
8085 kOSKextLogErrorLevel |
8086 kOSKextLogIPCFlag,
8087 "Recieved kext request from user space with no predicate.");
8088 result = kOSKextReturnInvalidArgument;
8089 goto finish;
8090 }
8091
8092 OSKextLog(/* kext */ NULL,
8093 kOSKextLogDebugLevel |
8094 kOSKextLogIPCFlag,
8095 "Received '%s' request from user space.",
8096 predicate->getCStringNoCopy());
8097
8098 result = kOSKextReturnNotPrivileged;
8099 if (hostPriv == HOST_PRIV_NULL) {
8100 /* must be root to use these kext requests */
8101 if (predicate->isEqualTo(kKextRequestPredicateUnload) ||
8102 predicate->isEqualTo(kKextRequestPredicateStart) ||
8103 predicate->isEqualTo(kKextRequestPredicateStop) ||
8104 predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
8105 predicate->isEqualTo(kKextRequestPredicateSendResource)) {
8106 OSKextLog(/* kext */ NULL,
8107 kOSKextLogErrorLevel |
8108 kOSKextLogIPCFlag,
8109 "Access Failure - must be root user.");
8110 goto finish;
8111 }
8112 }
8113
8114 /* Get common args in anticipation of use.
8115 */
8116 kextIdentifier = OSDynamicCast(OSString, _OSKextGetRequestArgument(
8117 requestDict, kKextRequestArgumentBundleIdentifierKey));
8118 kextIdentifiers = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
8119 requestDict, kKextRequestArgumentBundleIdentifierKey));
8120 if (kextIdentifier) {
8121 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
8122 }
8123 boolArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
8124 requestDict, kKextRequestArgumentValueKey));
8125
8126 result = kOSKextReturnInvalidArgument;
8127
8128 if (predicate->isEqualTo(kKextRequestPredicateStart)) {
8129 if (!kextIdentifier) {
8130 OSKextLog(/* kext */ NULL,
8131 kOSKextLogErrorLevel |
8132 kOSKextLogIPCFlag,
8133 "Invalid arguments to kext start request.");
8134 } else if (!theKext) {
8135 OSKextLog(/* kext */ NULL,
8136 kOSKextLogErrorLevel |
8137 kOSKextLogIPCFlag,
8138 "Kext %s not found for start request.",
8139 kextIdentifier->getCStringNoCopy());
8140 result = kOSKextReturnNotFound;
8141 } else {
8142 result = theKext->start();
8143 }
8144 } else if (predicate->isEqualTo(kKextRequestPredicateStop)) {
8145 if (!kextIdentifier) {
8146 OSKextLog(/* kext */ NULL,
8147 kOSKextLogErrorLevel |
8148 kOSKextLogIPCFlag,
8149 "Invalid arguments to kext stop request.");
8150 } else if (!theKext) {
8151 OSKextLog(/* kext */ NULL,
8152 kOSKextLogErrorLevel |
8153 kOSKextLogIPCFlag,
8154 "Kext %s not found for stop request.",
8155 kextIdentifier->getCStringNoCopy());
8156 result = kOSKextReturnNotFound;
8157 } else {
8158 result = theKext->stop();
8159 }
8160 } else if (predicate->isEqualTo(kKextRequestPredicateUnload)) {
8161 if (!kextIdentifier) {
8162 OSKextLog(/* kext */ NULL,
8163 kOSKextLogErrorLevel |
8164 kOSKextLogIPCFlag,
8165 "Invalid arguments to kext unload request.");
8166 } else if (!theKext) {
8167 OSKextLog(/* kext */ NULL,
8168 kOSKextLogErrorLevel |
8169 kOSKextLogIPCFlag,
8170 "Kext %s not found for unload request.",
8171 kextIdentifier->getCStringNoCopy());
8172 result = kOSKextReturnNotFound;
8173 } else {
8174 OSBoolean * terminateFlag = OSDynamicCast(OSBoolean,
8175 _OSKextGetRequestArgument(requestDict,
8176 kKextRequestArgumentTerminateIOServicesKey));
8177 result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue);
8178 }
8179 } else if (predicate->isEqualTo(kKextRequestPredicateSendResource)) {
8180 result = OSKext::dispatchResource(requestDict);
8181 } else if (predicate->isEqualTo(kKextRequestPredicateGetUUIDByAddress)) {
8182 OSNumber *lookupNum = NULL;
8183 lookupNum = OSDynamicCast(OSNumber,
8184 _OSKextGetRequestArgument(requestDict,
8185 kKextRequestArgumentLookupAddressKey));
8186
8187 responseObject = OSKext::copyKextUUIDForAddress(lookupNum);
8188 if (responseObject) {
8189 result = kOSReturnSuccess;
8190 } else {
8191 goto finish;
8192 }
8193 } else if (predicate->isEqualTo(kKextRequestPredicateGetLoaded) ||
8194 predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) {
8195 OSBoolean * delayAutounloadBool = NULL;
8196 OSObject * infoKeysRaw = NULL;
8197 OSArray * infoKeys = NULL;
8198 uint32_t infoKeysCount = 0;
8199
8200 delayAutounloadBool = OSDynamicCast(OSBoolean,
8201 _OSKextGetRequestArgument(requestDict,
8202 kKextRequestArgumentDelayAutounloadKey));
8203
8204 /* If asked to delay autounload, reset the timer if it's currently set.
8205 * (That is, don't schedule an unload if one isn't already pending.
8206 */
8207 if (delayAutounloadBool == kOSBooleanTrue) {
8208 OSKext::considerUnloads(/* rescheduleOnly? */ true);
8209 }
8210
8211 infoKeysRaw = _OSKextGetRequestArgument(requestDict,
8212 kKextRequestArgumentInfoKeysKey);
8213 infoKeys = OSDynamicCast(OSArray, infoKeysRaw);
8214 if (infoKeysRaw && !infoKeys) {
8215 OSKextLog(/* kext */ NULL,
8216 kOSKextLogErrorLevel |
8217 kOSKextLogIPCFlag,
8218 "Invalid arguments to kext info request.");
8219 goto finish;
8220 }
8221
8222 if (infoKeys) {
8223 infoKeysCount = infoKeys->getCount();
8224 for (uint32_t i = 0; i < infoKeysCount; i++) {
8225 if (!OSDynamicCast(OSString, infoKeys->getObject(i))) {
8226 OSKextLog(/* kext */ NULL,
8227 kOSKextLogErrorLevel |
8228 kOSKextLogIPCFlag,
8229 "Invalid arguments to kext info request.");
8230 goto finish;
8231 }
8232 }
8233 }
8234
8235 if (predicate->isEqualTo(kKextRequestPredicateGetLoaded)) {
8236 responseObject = OSKext::copyLoadedKextInfo(kextIdentifiers, infoKeys);
8237 } else if (predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) {
8238 responseObject = OSKext::copyLoadedKextInfoByUUID(kextIdentifiers, infoKeys);
8239 }
8240 if (!responseObject) {
8241 result = kOSKextReturnInternalError;
8242 } else {
8243 OSKextLog(/* kext */ NULL,
8244 kOSKextLogDebugLevel |
8245 kOSKextLogIPCFlag,
8246 "Returning loaded kext info.");
8247 result = kOSReturnSuccess;
8248 }
8249 } else if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
8250 /* Hand the current sKernelRequests array to the caller
8251 * (who must release it), and make a new one.
8252 */
8253 responseObject = sKernelRequests;
8254 sKernelRequests = OSArray::withCapacity(0);
8255 sPostedKextLoadIdentifiers->flushCollection();
8256 OSKextLog(/* kext */ NULL,
8257 kOSKextLogDebugLevel |
8258 kOSKextLogIPCFlag,
8259 "Returning kernel requests.");
8260 result = kOSReturnSuccess;
8261 } else if (predicate->isEqualTo(kKextRequestPredicateGetAllLoadRequests)) {
8262 /* Return the set of all requested bundle identifiers */
8263 responseObject = sAllKextLoadIdentifiers;
8264 responseObject->retain();
8265 OSKextLog(/* kext */ NULL,
8266 kOSKextLogDebugLevel |
8267 kOSKextLogIPCFlag,
8268 "Returning load requests.");
8269 result = kOSReturnSuccess;
8270 } else {
8271 OSKextLog(/* kext */ NULL,
8272 kOSKextLogDebugLevel |
8273 kOSKextLogIPCFlag,
8274 "Received '%s' invalid request from user space.",
8275 predicate->getCStringNoCopy());
8276 goto finish;
8277 }
8278
8279 /**********
8280 * Now we have handle the request, or not. Gather up the response & logging
8281 * info to ship to user space.
8282 *********/
8283
8284 /* Note: Nothing in OSKext is supposed to retain requestDict,
8285 * but you never know....
8286 */
8287 if (requestDict->getRetainCount() > 1) {
8288 OSKextLog(/* kext */ NULL,
8289 kOSKextLogWarningLevel |
8290 kOSKextLogIPCFlag,
8291 "Request from user space still retained by a kext; "
8292 "probable memory leak.");
8293 }
8294
8295 if (responseOut && responseObject) {
8296 serializer = OSSerialize::withCapacity(0);
8297 if (!serializer) {
8298 result = kOSKextReturnNoMemory;
8299 goto finish;
8300 }
8301
8302 if (!responseObject->serialize(serializer)) {
8303 OSKextLog(/* kext */ NULL,
8304 kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
8305 "Failed to serialize response to request from user space.");
8306 result = kOSKextReturnSerialization;
8307 goto finish;
8308 }
8309
8310 response = (char *)serializer->text();
8311 responseLength = serializer->getLength();
8312 }
8313
8314 if (responseOut && response) {
8315 char * buffer;
8316
8317 /* This kmem_alloc sets the return value of the function.
8318 */
8319 kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer,
8320 round_page(responseLength), VM_KERN_MEMORY_OSKEXT);
8321 if (kmem_result != KERN_SUCCESS) {
8322 OSKextLog(/* kext */ NULL,
8323 kOSKextLogErrorLevel |
8324 kOSKextLogIPCFlag,
8325 "Failed to copy response to request from user space.");
8326 result = kmem_result;
8327 goto finish;
8328 } else {
8329 /* 11981737 - clear uninitialized data in last page */
8330 bzero((void *)(buffer + responseLength),
8331 (round_page(responseLength) - responseLength));
8332 memcpy(buffer, response, responseLength);
8333 *responseOut = buffer;
8334 *responseLengthOut = responseLength;
8335 }
8336 }
8337
8338 finish:
8339
8340 /* Gather up the collected log messages for user space. Any messages
8341 * messages past this call will not make it up as log messages but
8342 * will be in the system log. Note that we ignore the return of the
8343 * serialize; it has no bearing on the operation at hand even if we
8344 * fail to get the log messages.
8345 */
8346 logInfoArray = OSKext::clearUserSpaceLogFilter();
8347
8348 if (logInfoArray && logInfoOut && logInfoLengthOut) {
8349 (void)OSKext::serializeLogInfo(logInfoArray,
8350 logInfoOut, logInfoLengthOut);
8351 }
8352
8353 IORecursiveLockUnlock(sKextLock);
8354
8355 OSSafeReleaseNULL(parsedXML);
8356 OSSafeReleaseNULL(errorString);
8357 OSSafeReleaseNULL(responseObject);
8358 OSSafeReleaseNULL(serializer);
8359 OSSafeReleaseNULL(logInfoArray);
8360
8361 return result;
8362 }
8363
8364
8365 // #include <InstrProfiling.h>
8366 extern "C" {
8367 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin,
8368 const char *DataEnd,
8369 const char *CountersBegin,
8370 const char *CountersEnd,
8371 const char *NamesBegin,
8372 const char *NamesEnd);
8373 int __llvm_profile_write_buffer_internal(char *Buffer,
8374 const char *DataBegin,
8375 const char *DataEnd,
8376 const char *CountersBegin,
8377 const char *CountersEnd,
8378 const char *NamesBegin,
8379 const char *NamesEnd);
8380 }
8381
8382
8383 static
8384 void
8385 OSKextPgoMetadataPut(char *pBuffer,
8386 size_t *position,
8387 size_t bufferSize,
8388 uint32_t *num_pairs,
8389 const char *key,
8390 const char *value)
8391 {
8392 size_t strlen_key = strlen(key);
8393 size_t strlen_value = strlen(value);
8394 size_t len = strlen(key) + 1 + strlen(value) + 1;
8395 char *pos = pBuffer + *position;
8396 *position += len;
8397 if (pBuffer && bufferSize && *position <= bufferSize) {
8398 memcpy(pos, key, strlen_key); pos += strlen_key;
8399 *(pos++) = '=';
8400 memcpy(pos, value, strlen_value); pos += strlen_value;
8401 *(pos++) = 0;
8402 if (num_pairs) {
8403 (*num_pairs)++;
8404 }
8405 }
8406 }
8407
8408
8409 static
8410 void
8411 OSKextPgoMetadataPutMax(size_t *position, const char *key, size_t value_max)
8412 {
8413 *position += strlen(key) + 1 + value_max + 1;
8414 }
8415
8416
8417 static
8418 void
8419 OSKextPgoMetadataPutAll(OSKext *kext,
8420 uuid_t instance_uuid,
8421 char *pBuffer,
8422 size_t *position,
8423 size_t bufferSize,
8424 uint32_t *num_pairs)
8425 {
8426 _static_assert_1_arg(sizeof(clock_sec_t) % 2 == 0);
8427 //log_10 2^16 ≈ 4.82
8428 const size_t max_secs_string_size = 5 * sizeof(clock_sec_t) / 2;
8429 const size_t max_timestamp_string_size = max_secs_string_size + 1 + 6;
8430
8431 if (!pBuffer) {
8432 OSKextPgoMetadataPutMax(position, "INSTANCE", 36);
8433 OSKextPgoMetadataPutMax(position, "UUID", 36);
8434 OSKextPgoMetadataPutMax(position, "TIMESTAMP", max_timestamp_string_size);
8435 } else {
8436 uuid_string_t instance_uuid_string;
8437 uuid_unparse(instance_uuid, instance_uuid_string);
8438 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
8439 "INSTANCE", instance_uuid_string);
8440
8441 OSData *uuid_data;
8442 uuid_t uuid;
8443 uuid_string_t uuid_string;
8444 uuid_data = kext->copyUUID();
8445 if (uuid_data) {
8446 memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
8447 OSSafeReleaseNULL(uuid_data);
8448 uuid_unparse(uuid, uuid_string);
8449 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
8450 "UUID", uuid_string);
8451 }
8452
8453 clock_sec_t secs;
8454 clock_usec_t usecs;
8455 clock_get_calendar_microtime(&secs, &usecs);
8456 assert(usecs < 1000000);
8457 char timestamp[max_timestamp_string_size + 1];
8458 _static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t));
8459 snprintf(timestamp, sizeof(timestamp), "%lu.%06d", (unsigned long)secs, (int)usecs);
8460 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
8461 "TIMESTAMP", timestamp);
8462 }
8463
8464 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
8465 "NAME", kext->getIdentifierCString());
8466
8467 char versionCString[kOSKextVersionMaxLength];
8468 OSKextVersionGetString(kext->getVersion(), versionCString, kOSKextVersionMaxLength);
8469 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
8470 "VERSION", versionCString);
8471 }
8472
8473 static
8474 size_t
8475 OSKextPgoMetadataSize(OSKext *kext)
8476 {
8477 size_t position = 0;
8478 uuid_t fakeuuid = {};
8479 OSKextPgoMetadataPutAll(kext, fakeuuid, NULL, &position, 0, NULL);
8480 return position;
8481 }
8482
8483 int
8484 OSKextGrabPgoDataLocked(OSKext *kext,
8485 bool metadata,
8486 uuid_t instance_uuid,
8487 uint64_t *pSize,
8488 char *pBuffer,
8489 uint64_t bufferSize)
8490 {
8491 int err = 0;
8492
8493 kernel_section_t *sect_prf_data = NULL;
8494 kernel_section_t *sect_prf_name = NULL;
8495 kernel_section_t *sect_prf_cnts = NULL;
8496 uint64_t size;
8497 size_t metadata_size = 0;
8498
8499 sect_prf_data = kext->lookupSection("__DATA", "__llvm_prf_data");
8500 sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_name");
8501 sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
8502
8503 if (!sect_prf_data || !sect_prf_name || !sect_prf_cnts) {
8504 err = ENOTSUP;
8505 goto out;
8506 }
8507
8508 size = __llvm_profile_get_size_for_buffer_internal(
8509 (const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
8510 (const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
8511 (const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
8512
8513 if (metadata) {
8514 metadata_size = OSKextPgoMetadataSize(kext);
8515 size += metadata_size;
8516 size += sizeof(pgo_metadata_footer);
8517 }
8518
8519
8520 if (pSize) {
8521 *pSize = size;
8522 }
8523
8524 if (pBuffer && bufferSize) {
8525 if (bufferSize < size) {
8526 err = ERANGE;
8527 goto out;
8528 }
8529
8530 err = __llvm_profile_write_buffer_internal(
8531 pBuffer,
8532 (const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
8533 (const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
8534 (const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
8535
8536 if (err) {
8537 err = EIO;
8538 goto out;
8539 }
8540
8541 if (metadata) {
8542 char *end_of_buffer = pBuffer + size;
8543 struct pgo_metadata_footer *footerp = (struct pgo_metadata_footer *) (end_of_buffer - sizeof(struct pgo_metadata_footer));
8544 char *metadata_buffer = end_of_buffer - (sizeof(struct pgo_metadata_footer) + metadata_size);
8545
8546 size_t metadata_position = 0;
8547 uint32_t num_pairs = 0;
8548 OSKextPgoMetadataPutAll(kext, instance_uuid, metadata_buffer, &metadata_position, metadata_size, &num_pairs);
8549 while (metadata_position < metadata_size) {
8550 metadata_buffer[metadata_position++] = 0;
8551 }
8552
8553 struct pgo_metadata_footer footer;
8554 footer.magic = htonl(0x6d657461);
8555 footer.number_of_pairs = htonl( num_pairs );
8556 footer.offset_to_pairs = htonl( sizeof(struct pgo_metadata_footer) + metadata_size );
8557 memcpy(footerp, &footer, sizeof(footer));
8558 }
8559 }
8560
8561 out:
8562 return err;
8563 }
8564
8565
8566 int
8567 OSKextGrabPgoData(uuid_t uuid,
8568 uint64_t *pSize,
8569 char *pBuffer,
8570 uint64_t bufferSize,
8571 int wait_for_unload,
8572 int metadata)
8573 {
8574 int err = 0;
8575 OSKext *kext = NULL;
8576
8577
8578 IORecursiveLockLock(sKextLock);
8579
8580 kext = OSKext::lookupKextWithUUID(uuid);
8581 if (!kext) {
8582 err = ENOENT;
8583 goto out;
8584 }
8585
8586 if (wait_for_unload) {
8587 OSKextGrabPgoStruct s;
8588
8589 s.metadata = metadata;
8590 s.pSize = pSize;
8591 s.pBuffer = pBuffer;
8592 s.bufferSize = bufferSize;
8593 s.err = EINTR;
8594
8595 struct list_head *prev = &kext->pendingPgoHead;
8596 struct list_head *next = kext->pendingPgoHead.next;
8597
8598 s.list_head.prev = prev;
8599 s.list_head.next = next;
8600
8601 prev->next = &s.list_head;
8602 next->prev = &s.list_head;
8603
8604 kext->release();
8605 kext = NULL;
8606
8607 IORecursiveLockSleep(sKextLock, &s, THREAD_ABORTSAFE);
8608
8609 prev = s.list_head.prev;
8610 next = s.list_head.next;
8611
8612 prev->next = next;
8613 next->prev = prev;
8614
8615 err = s.err;
8616 } else {
8617 err = OSKextGrabPgoDataLocked(kext, metadata, kext->instance_uuid, pSize, pBuffer, bufferSize);
8618 }
8619
8620 out:
8621 if (kext) {
8622 kext->release();
8623 }
8624
8625 IORecursiveLockUnlock(sKextLock);
8626
8627 return err;
8628 }
8629
8630 void
8631 OSKextResetPgoCountersLock()
8632 {
8633 IORecursiveLockLock(sKextLock);
8634 }
8635
8636 void
8637 OSKextResetPgoCountersUnlock()
8638 {
8639 IORecursiveLockUnlock(sKextLock);
8640 }
8641
8642
8643 extern unsigned int not_in_kdp;
8644
8645 void
8646 OSKextResetPgoCounters()
8647 {
8648 assert(!not_in_kdp);
8649 uint32_t count = sLoadedKexts->getCount();
8650 for (uint32_t i = 0; i < count; i++) {
8651 OSKext *kext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
8652 kernel_section_t *sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
8653 if (!sect_prf_cnts) {
8654 continue;
8655 }
8656 memset((void*)sect_prf_cnts->addr, 0, sect_prf_cnts->size);
8657 }
8658 }
8659
8660 OSDictionary *
8661 OSKext::copyLoadedKextInfoByUUID(
8662 OSArray * kextIdentifiers,
8663 OSArray * infoKeys)
8664 {
8665 OSDictionary * result = NULL;
8666 OSDictionary * kextInfo = NULL; // must release
8667 uint32_t count, i;
8668 uint32_t idCount = 0;
8669 uint32_t idIndex = 0;
8670
8671 IORecursiveLockLock(sKextLock);
8672
8673 #if CONFIG_MACF
8674 /* Is the calling process allowed to query kext info? */
8675 if (current_task() != kernel_task) {
8676 int macCheckResult = 0;
8677 kauth_cred_t cred = NULL;
8678
8679 cred = kauth_cred_get_with_ref();
8680 macCheckResult = mac_kext_check_query(cred);
8681 kauth_cred_unref(&cred);
8682
8683 if (macCheckResult != 0) {
8684 OSKextLog(/* kext */ NULL,
8685 kOSKextLogErrorLevel | kOSKextLogLoadFlag,
8686 "Failed to query kext info (MAC policy error 0x%x).",
8687 macCheckResult);
8688 goto finish;
8689 }
8690 }
8691 #endif
8692
8693 /* Empty list of UUIDs is equivalent to no list (get all).
8694 */
8695 if (kextIdentifiers && !kextIdentifiers->getCount()) {
8696 kextIdentifiers = NULL;
8697 } else if (kextIdentifiers) {
8698 idCount = kextIdentifiers->getCount();
8699 }
8700
8701 /* Same for keys.
8702 */
8703 if (infoKeys && !infoKeys->getCount()) {
8704 infoKeys = NULL;
8705 }
8706
8707 count = sLoadedKexts->getCount();
8708 result = OSDictionary::withCapacity(count);
8709 if (!result) {
8710 goto finish;
8711 }
8712
8713 for (i = 0; i < count; i++) {
8714 OSKext *thisKext = NULL;// do not release
8715 Boolean includeThis = true;
8716 uuid_t thisKextUUID;
8717 uuid_t thisKextTextUUID;
8718 OSData *uuid_data;
8719 uuid_string_t uuid_key;
8720
8721 thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
8722 if (!thisKext) {
8723 continue;
8724 }
8725
8726 uuid_data = thisKext->copyUUID();
8727 if (!uuid_data) {
8728 continue;
8729 }
8730
8731 memcpy(&thisKextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextUUID));
8732 OSSafeReleaseNULL(uuid_data);
8733
8734 uuid_unparse(thisKextUUID, uuid_key);
8735
8736 uuid_data = thisKext->copyTextUUID();
8737 if (!uuid_data) {
8738 continue;
8739 }
8740 memcpy(&thisKextTextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextTextUUID));
8741 OSSafeReleaseNULL(uuid_data);
8742
8743 /* Skip current kext if we have a list of UUIDs and
8744 * it isn't in the list.
8745 */
8746 if (kextIdentifiers) {
8747 includeThis = false;
8748
8749 for (idIndex = 0; idIndex < idCount; idIndex++) {
8750 const OSString* wantedUUID = OSDynamicCast(OSString,
8751 kextIdentifiers->getObject(idIndex));
8752
8753 uuid_t uuid;
8754 uuid_parse(wantedUUID->getCStringNoCopy(), uuid);
8755
8756 if ((0 == uuid_compare(uuid, thisKextUUID))
8757 || (0 == uuid_compare(uuid, thisKextTextUUID))) {
8758 includeThis = true;
8759 /* Only need to find the first kext if multiple match,
8760 * ie. asking for the kernel uuid does not need to find
8761 * interface kexts or builtin static kexts.
8762 */
8763 kextIdentifiers->removeObject(idIndex);
8764 uuid_unparse(uuid, uuid_key);
8765 break;
8766 }
8767 }
8768 }
8769
8770 if (!includeThis) {
8771 continue;
8772 }
8773
8774 kextInfo = thisKext->copyInfo(infoKeys);
8775 if (kextInfo) {
8776 result->setObject(uuid_key, kextInfo);
8777 kextInfo->release();
8778 }
8779
8780 if (kextIdentifiers && !kextIdentifiers->getCount()) {
8781 break;
8782 }
8783 }
8784
8785 finish:
8786 IORecursiveLockUnlock(sKextLock);
8787
8788 return result;
8789 }
8790
8791 /*********************************************************************
8792 *********************************************************************/
8793 /* static */
8794 OSDictionary *
8795 OSKext::copyLoadedKextInfo(
8796 OSArray * kextIdentifiers,
8797 OSArray * infoKeys)
8798 {
8799 OSDictionary * result = NULL;
8800 uint32_t idCount = 0;
8801 bool onlyLoaded;
8802
8803 IORecursiveLockLock(sKextLock);
8804
8805 #if CONFIG_MACF
8806 /* Is the calling process allowed to query kext info? */
8807 if (current_task() != kernel_task) {
8808 int macCheckResult = 0;
8809 kauth_cred_t cred = NULL;
8810
8811 cred = kauth_cred_get_with_ref();
8812 macCheckResult = mac_kext_check_query(cred);
8813 kauth_cred_unref(&cred);
8814
8815 if (macCheckResult != 0) {
8816 OSKextLog(/* kext */ NULL,
8817 kOSKextLogErrorLevel | kOSKextLogLoadFlag,
8818 "Failed to query kext info (MAC policy error 0x%x).",
8819 macCheckResult);
8820 goto finish;
8821 }
8822 }
8823 #endif
8824
8825 /* Empty list of bundle ids is equivalent to no list (get all).
8826 */
8827 if (kextIdentifiers && !kextIdentifiers->getCount()) {
8828 kextIdentifiers = NULL;
8829 } else if (kextIdentifiers) {
8830 idCount = kextIdentifiers->getCount();
8831 }
8832
8833 /* Same for keys.
8834 */
8835 if (infoKeys && !infoKeys->getCount()) {
8836 infoKeys = NULL;
8837 }
8838
8839 onlyLoaded = (!infoKeys || !_OSArrayContainsCString(infoKeys, kOSBundleAllPrelinkedKey));
8840
8841 result = OSDictionary::withCapacity(128);
8842 if (!result) {
8843 goto finish;
8844 }
8845
8846 #if 0
8847 OSKextLog(/* kext */ NULL,
8848 kOSKextLogErrorLevel |
8849 kOSKextLogGeneralFlag,
8850 "kaslr: vm_kernel_slide 0x%lx \n",
8851 vm_kernel_slide);
8852 OSKextLog(/* kext */ NULL,
8853 kOSKextLogErrorLevel |
8854 kOSKextLogGeneralFlag,
8855 "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n",
8856 vm_kernel_stext, vm_kernel_etext);
8857 OSKextLog(/* kext */ NULL,
8858 kOSKextLogErrorLevel |
8859 kOSKextLogGeneralFlag,
8860 "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n",
8861 vm_kernel_base, vm_kernel_top);
8862 OSKextLog(/* kext */ NULL,
8863 kOSKextLogErrorLevel |
8864 kOSKextLogGeneralFlag,
8865 "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n",
8866 vm_kext_base, vm_kext_top);
8867 OSKextLog(/* kext */ NULL,
8868 kOSKextLogErrorLevel |
8869 kOSKextLogGeneralFlag,
8870 "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n",
8871 vm_prelink_stext, vm_prelink_etext);
8872 OSKextLog(/* kext */ NULL,
8873 kOSKextLogErrorLevel |
8874 kOSKextLogGeneralFlag,
8875 "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n",
8876 vm_prelink_sinfo, vm_prelink_einfo);
8877 OSKextLog(/* kext */ NULL,
8878 kOSKextLogErrorLevel |
8879 kOSKextLogGeneralFlag,
8880 "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n",
8881 vm_slinkedit, vm_elinkedit);
8882 #endif
8883
8884 sKextsByID->iterateObjects(^bool (const OSSymbol * thisKextID, OSObject * obj)
8885 {
8886 OSKext * thisKext = NULL;// do not release
8887 Boolean includeThis = true;
8888 OSDictionary * kextInfo = NULL;// must release
8889
8890 thisKext = OSDynamicCast(OSKext, obj);
8891 if (!thisKext) {
8892 return false;;
8893 }
8894
8895 /* Skip current kext if not yet started and caller didn't request all.
8896 */
8897 if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
8898 return false;;
8899 }
8900
8901 /* Skip current kext if we have a list of bundle IDs and
8902 * it isn't in the list.
8903 */
8904 if (kextIdentifiers) {
8905 includeThis = false;
8906
8907 for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
8908 const OSString * thisRequestID = OSDynamicCast(OSString,
8909 kextIdentifiers->getObject(idIndex));
8910 if (thisKextID->isEqualTo(thisRequestID)) {
8911 includeThis = true;
8912 break;
8913 }
8914 }
8915 }
8916
8917 if (!includeThis) {
8918 return false;
8919 }
8920
8921 kextInfo = thisKext->copyInfo(infoKeys);
8922 if (kextInfo) {
8923 result->setObject(thisKext->getIdentifier(), kextInfo);
8924 kextInfo->release();
8925 }
8926 return false;
8927 });
8928
8929 finish:
8930 IORecursiveLockUnlock(sKextLock);
8931
8932 return result;
8933 }
8934
8935 /*********************************************************************
8936 * Any info that needs to do allocations must goto finish on alloc
8937 * failure. Info that is just a lookup should just not set the object
8938 * if the info does not exist.
8939 *********************************************************************/
8940 #define _OSKextLoadInfoDictCapacity (12)
8941
8942 OSDictionary *
8943 OSKext::copyInfo(OSArray * infoKeys)
8944 {
8945 OSDictionary * result = NULL;
8946 bool success = false;
8947 OSData * headerData = NULL;// must release
8948 OSData * logData = NULL;// must release
8949 OSNumber * cpuTypeNumber = NULL;// must release
8950 OSNumber * cpuSubtypeNumber = NULL;// must release
8951 OSString * versionString = NULL;// do not release
8952 uint32_t executablePathCStringSize = 0;
8953 char * executablePathCString = NULL;// must release
8954 OSString * executablePathString = NULL;// must release
8955 OSData * uuid = NULL;// must release
8956 OSNumber * scratchNumber = NULL;// must release
8957 OSArray * dependencyLoadTags = NULL;// must release
8958 OSCollectionIterator * metaClassIterator = NULL;// must release
8959 OSArray * metaClassInfo = NULL;// must release
8960 OSDictionary * metaClassDict = NULL;// must release
8961 OSMetaClass * thisMetaClass = NULL;// do not release
8962 OSString * metaClassName = NULL;// must release
8963 OSString * superclassName = NULL;// must release
8964 uint32_t count, i;
8965
8966 result = OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity);
8967 if (!result) {
8968 goto finish;
8969 }
8970
8971
8972 /* Empty keys means no keys, but NULL is quicker to check.
8973 */
8974 if (infoKeys && !infoKeys->getCount()) {
8975 infoKeys = NULL;
8976 }
8977
8978 /* Headers, CPU type, and CPU subtype.
8979 */
8980 if (!infoKeys ||
8981 _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey) ||
8982 _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey) ||
8983 _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey) ||
8984 _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
8985 if (linkedExecutable && !isInterface()) {
8986 kernel_mach_header_t *kext_mach_hdr = (kernel_mach_header_t *)
8987 linkedExecutable->getBytesNoCopy();
8988
8989 #if !SECURE_KERNEL
8990 // do not return macho header info on shipping iOS - 19095897
8991 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey)) {
8992 kernel_mach_header_t * temp_kext_mach_hdr;
8993 struct load_command * lcp;
8994
8995 headerData = OSData::withBytes(kext_mach_hdr,
8996 (u_int) (sizeof(*kext_mach_hdr) + kext_mach_hdr->sizeofcmds));
8997 if (!headerData) {
8998 goto finish;
8999 }
9000
9001 // unslide any vmaddrs we return to userspace - 10726716
9002 temp_kext_mach_hdr = (kernel_mach_header_t *)
9003 headerData->getBytesNoCopy();
9004 if (temp_kext_mach_hdr == NULL) {
9005 goto finish;
9006 }
9007
9008 lcp = (struct load_command *) (temp_kext_mach_hdr + 1);
9009 for (i = 0; i < temp_kext_mach_hdr->ncmds; i++) {
9010 if (lcp->cmd == LC_SEGMENT_KERNEL) {
9011 kernel_segment_command_t * segp;
9012 kernel_section_t * secp;
9013
9014 segp = (kernel_segment_command_t *) lcp;
9015 // 10543468 - if we jettisoned __LINKEDIT clear size info
9016 if (flags.jettisonLinkeditSeg) {
9017 if (strncmp(segp->segname, SEG_LINKEDIT, sizeof(segp->segname)) == 0) {
9018 segp->vmsize = 0;
9019 segp->fileoff = 0;
9020 segp->filesize = 0;
9021 }
9022 }
9023
9024 #if 0
9025 OSKextLog(/* kext */ NULL,
9026 kOSKextLogErrorLevel |
9027 kOSKextLogGeneralFlag,
9028 "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
9029 __FUNCTION__, segp->segname, segp->vmaddr,
9030 VM_KERNEL_UNSLIDE(segp->vmaddr),
9031 segp->vmsize, segp->nsects);
9032 if ((VM_KERNEL_IS_SLID(segp->vmaddr) == false) &&
9033 (VM_KERNEL_IS_KEXT(segp->vmaddr) == false) &&
9034 (VM_KERNEL_IS_PRELINKTEXT(segp->vmaddr) == false) &&
9035 (VM_KERNEL_IS_PRELINKINFO(segp->vmaddr) == false) &&
9036 (VM_KERNEL_IS_KEXT_LINKEDIT(segp->vmaddr) == false)) {
9037 OSKextLog(/* kext */ NULL,
9038 kOSKextLogErrorLevel |
9039 kOSKextLogGeneralFlag,
9040 "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX",
9041 __FUNCTION__, segp->vmaddr, vm_kext_base, vm_kext_top);
9042 }
9043 #endif
9044 segp->vmaddr = ml_static_unslide(segp->vmaddr);
9045
9046 for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
9047 secp->addr = ml_static_unslide(secp->addr);
9048 }
9049 }
9050 lcp = (struct load_command *)((caddr_t)lcp + lcp->cmdsize);
9051 }
9052 result->setObject(kOSBundleMachOHeadersKey, headerData);
9053 }
9054 #endif // SECURE_KERNEL
9055
9056 if (_OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
9057 osLogDataHeaderRef *header;
9058 char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
9059
9060 void *os_log_data = NULL;
9061 void *cstring_data = NULL;
9062 unsigned long os_log_size = 0;
9063 unsigned long cstring_size = 0;
9064 uint32_t os_log_offset = 0;
9065 uint32_t cstring_offset = 0;
9066 bool res;
9067
9068 os_log_data = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__os_log", &os_log_size);
9069 os_log_offset = getsectoffsetfromheader(kext_mach_hdr, "__TEXT", "__os_log");
9070 cstring_data = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__cstring", &cstring_size);
9071 cstring_offset = getsectoffsetfromheader(kext_mach_hdr, "__TEXT", "__cstring");
9072
9073 header = (osLogDataHeaderRef *) headerBytes;
9074 header->version = OS_LOG_HDR_VERSION;
9075 header->sect_count = NUM_OS_LOG_SECTIONS;
9076 header->sections[OS_LOG_SECT_IDX].sect_offset = os_log_offset;
9077 header->sections[OS_LOG_SECT_IDX].sect_size = (uint32_t) os_log_size;
9078 header->sections[CSTRING_SECT_IDX].sect_offset = cstring_offset;
9079 header->sections[CSTRING_SECT_IDX].sect_size = (uint32_t) cstring_size;
9080
9081
9082 logData = OSData::withBytes(header, (u_int) (sizeof(osLogDataHeaderRef)));
9083 if (!logData) {
9084 goto finish;
9085 }
9086 res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
9087 if (!res) {
9088 goto finish;
9089 }
9090 if (os_log_data) {
9091 res = logData->appendBytes(os_log_data, (u_int)header->sections[OS_LOG_SECT_IDX].sect_size);
9092 if (!res) {
9093 goto finish;
9094 }
9095 }
9096 if (cstring_data) {
9097 res = logData->appendBytes(cstring_data, (u_int)header->sections[CSTRING_SECT_IDX].sect_size);
9098 if (!res) {
9099 goto finish;
9100 }
9101 }
9102 result->setObject(kOSBundleLogStringsKey, logData);
9103 }
9104
9105 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey)) {
9106 cpuTypeNumber = OSNumber::withNumber(
9107 (uint64_t) kext_mach_hdr->cputype,
9108 8 * sizeof(kext_mach_hdr->cputype));
9109 if (!cpuTypeNumber) {
9110 goto finish;
9111 }
9112 result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber);
9113 }
9114
9115 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
9116 cpuSubtypeNumber = OSNumber::withNumber(
9117 (uint64_t) kext_mach_hdr->cpusubtype,
9118 8 * sizeof(kext_mach_hdr->cpusubtype));
9119 if (!cpuSubtypeNumber) {
9120 goto finish;
9121 }
9122 result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber);
9123 }
9124 }
9125 }
9126
9127 /* CFBundleIdentifier. We set this regardless because it's just stupid not to.
9128 */
9129 result->setObject(kCFBundleIdentifierKey, bundleID);
9130
9131 /* CFBundleVersion.
9132 */
9133 if (!infoKeys || _OSArrayContainsCString(infoKeys, kCFBundleVersionKey)) {
9134 versionString = OSDynamicCast(OSString,
9135 getPropertyForHostArch(kCFBundleVersionKey));
9136 if (versionString) {
9137 result->setObject(kCFBundleVersionKey, versionString);
9138 }
9139 }
9140
9141 /* OSBundleCompatibleVersion.
9142 */
9143 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCompatibleVersionKey)) {
9144 versionString = OSDynamicCast(OSString,
9145 getPropertyForHostArch(kOSBundleCompatibleVersionKey));
9146 if (versionString) {
9147 result->setObject(kOSBundleCompatibleVersionKey, versionString);
9148 }
9149 }
9150
9151 /* Path.
9152 */
9153 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePathKey)) {
9154 if (path) {
9155 result->setObject(kOSBundlePathKey, path);
9156 }
9157 }
9158
9159
9160 /* OSBundleExecutablePath.
9161 */
9162 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecutablePathKey)) {
9163 if (path && executableRelPath) {
9164 uint32_t pathLength = path->getLength(); // gets incremented below
9165
9166 // +1 for slash, +1 for \0
9167 executablePathCStringSize = pathLength + executableRelPath->getLength() + 2;
9168
9169 executablePathCString = (char *)kalloc_tag((executablePathCStringSize) *
9170 sizeof(char), VM_KERN_MEMORY_OSKEXT); // +1 for \0
9171 if (!executablePathCString) {
9172 goto finish;
9173 }
9174 strlcpy(executablePathCString, path->getCStringNoCopy(),
9175 executablePathCStringSize);
9176 executablePathCString[pathLength++] = '/';
9177 executablePathCString[pathLength++] = '\0';
9178 strlcat(executablePathCString, executableRelPath->getCStringNoCopy(),
9179 executablePathCStringSize);
9180
9181 executablePathString = OSString::withCString(executablePathCString);
9182
9183 if (!executablePathString) {
9184 goto finish;
9185 }
9186
9187 result->setObject(kOSBundleExecutablePathKey, executablePathString);
9188 } else if (flags.builtin) {
9189 result->setObject(kOSBundleExecutablePathKey, bundleID);
9190 }
9191 }
9192
9193 /* UUID, if the kext has one.
9194 */
9195 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) {
9196 uuid = copyUUID();
9197 if (uuid) {
9198 result->setObject(kOSBundleUUIDKey, uuid);
9199 uuid->release();
9200 }
9201 }
9202 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleTextUUIDKey)) {
9203 uuid = copyTextUUID();
9204 if (uuid) {
9205 result->setObject(kOSBundleTextUUIDKey, uuid); uuid->release();
9206 }
9207 }
9208
9209 /*****
9210 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
9211 */
9212 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKernelResourceKey)) {
9213 result->setObject(kOSKernelResourceKey,
9214 isKernelComponent() ? kOSBooleanTrue : kOSBooleanFalse);
9215 }
9216
9217 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleIsInterfaceKey)) {
9218 result->setObject(kOSBundleIsInterfaceKey,
9219 isInterface() ? kOSBooleanTrue : kOSBooleanFalse);
9220 }
9221
9222 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePrelinkedKey)) {
9223 result->setObject(kOSBundlePrelinkedKey,
9224 isPrelinked() ? kOSBooleanTrue : kOSBooleanFalse);
9225 }
9226
9227 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleStartedKey)) {
9228 result->setObject(kOSBundleStartedKey,
9229 isStarted() ? kOSBooleanTrue : kOSBooleanFalse);
9230 }
9231
9232 /* LoadTag (Index).
9233 */
9234 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadTagKey)) {
9235 scratchNumber = OSNumber::withNumber((unsigned long long)loadTag,
9236 /* numBits */ 8 * sizeof(loadTag));
9237 if (!scratchNumber) {
9238 goto finish;
9239 }
9240 result->setObject(kOSBundleLoadTagKey, scratchNumber);
9241 OSSafeReleaseNULL(scratchNumber);
9242 }
9243
9244 /* LoadAddress, LoadSize.
9245 */
9246 if (!infoKeys ||
9247 _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey) ||
9248 _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey) ||
9249 _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey) ||
9250 _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey) ||
9251 _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
9252 if (isInterface() || flags.builtin || linkedExecutable) {
9253 /* These go to userspace via serialization, so we don't want any doubts
9254 * about their size.
9255 */
9256 uint64_t loadAddress = 0;
9257 uint32_t loadSize = 0;
9258 uint32_t wiredSize = 0;
9259 uint64_t execLoadAddress = 0;
9260 uint32_t execLoadSize = 0;
9261
9262 /* Interfaces always report 0 load address & size.
9263 * Just the way they roll.
9264 *
9265 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
9266 * xxx - shouldn't have one!
9267 */
9268
9269 if (flags.builtin || linkedExecutable) {
9270 kernel_mach_header_t *mh = NULL;
9271 kernel_segment_command_t *seg = NULL;
9272
9273 if (flags.builtin) {
9274 loadAddress = kmod_info->address;
9275 loadSize = kmod_info->size;
9276 } else {
9277 loadAddress = (uint64_t)linkedExecutable->getBytesNoCopy();
9278 loadSize = linkedExecutable->getLength();
9279 }
9280 mh = (kernel_mach_header_t *)loadAddress;
9281 loadAddress = ml_static_unslide(loadAddress);
9282
9283 /* Walk through the kext, looking for the first executable
9284 * segment in case we were asked for its size/address.
9285 */
9286 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
9287 if (seg->initprot & VM_PROT_EXECUTE) {
9288 execLoadAddress = ml_static_unslide(seg->vmaddr);
9289 execLoadSize = seg->vmsize;
9290 break;
9291 }
9292 }
9293
9294 /* If we have a kmod_info struct, calculated the wired size
9295 * from that. Otherwise it's the full load size.
9296 */
9297 if (kmod_info) {
9298 wiredSize = loadSize - kmod_info->hdr_size;
9299 } else {
9300 wiredSize = loadSize;
9301 }
9302 }
9303
9304 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey)) {
9305 scratchNumber = OSNumber::withNumber(
9306 (unsigned long long)(loadAddress),
9307 /* numBits */ 8 * sizeof(loadAddress));
9308 if (!scratchNumber) {
9309 goto finish;
9310 }
9311 result->setObject(kOSBundleLoadAddressKey, scratchNumber);
9312 OSSafeReleaseNULL(scratchNumber);
9313 }
9314 #if CONFIG_EMBEDDED
9315 if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCacheLoadAddressKey))
9316 && loadAddress && loadSize) {
9317 scratchNumber = OSNumber::withNumber(
9318 (unsigned long long)ml_static_unslide((uintptr_t)segLOWESTTEXT),
9319 /* numBits */ 8 * sizeof(loadAddress));
9320 if (!scratchNumber) {
9321 goto finish;
9322 }
9323 result->setObject(kOSBundleCacheLoadAddressKey, scratchNumber);
9324 OSSafeReleaseNULL(scratchNumber);
9325 }
9326 if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleKextsInKernelTextKey))
9327 && (this == sKernelKext) && gBuiltinKmodsCount) {
9328 result->setObject(kOSBundleKextsInKernelTextKey, kOSBooleanTrue);
9329 }
9330 #endif /* CONFIG_EMBEDDED */
9331 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey)) {
9332 scratchNumber = OSNumber::withNumber(
9333 (unsigned long long)(execLoadAddress),
9334 /* numBits */ 8 * sizeof(execLoadAddress));
9335 if (!scratchNumber) {
9336 goto finish;
9337 }
9338 result->setObject(kOSBundleExecLoadAddressKey, scratchNumber);
9339 OSSafeReleaseNULL(scratchNumber);
9340 }
9341 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey)) {
9342 scratchNumber = OSNumber::withNumber(
9343 (unsigned long long)(loadSize),
9344 /* numBits */ 8 * sizeof(loadSize));
9345 if (!scratchNumber) {
9346 goto finish;
9347 }
9348 result->setObject(kOSBundleLoadSizeKey, scratchNumber);
9349 OSSafeReleaseNULL(scratchNumber);
9350 }
9351 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey)) {
9352 scratchNumber = OSNumber::withNumber(
9353 (unsigned long long)(execLoadSize),
9354 /* numBits */ 8 * sizeof(execLoadSize));
9355 if (!scratchNumber) {
9356 goto finish;
9357 }
9358 result->setObject(kOSBundleExecLoadSizeKey, scratchNumber);
9359 OSSafeReleaseNULL(scratchNumber);
9360 }
9361 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
9362 scratchNumber = OSNumber::withNumber(
9363 (unsigned long long)(wiredSize),
9364 /* numBits */ 8 * sizeof(wiredSize));
9365 if (!scratchNumber) {
9366 goto finish;
9367 }
9368 result->setObject(kOSBundleWiredSizeKey, scratchNumber);
9369 OSSafeReleaseNULL(scratchNumber);
9370 }
9371 }
9372 }
9373
9374 /* OSBundleDependencies. In descending order for
9375 * easy compatibility with kextstat(8).
9376 */
9377 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleDependenciesKey)) {
9378 if ((count = getNumDependencies())) {
9379 dependencyLoadTags = OSArray::withCapacity(count);
9380 result->setObject(kOSBundleDependenciesKey, dependencyLoadTags);
9381
9382 i = count - 1;
9383 do {
9384 OSKext * dependency = OSDynamicCast(OSKext,
9385 dependencies->getObject(i));
9386
9387 OSSafeReleaseNULL(scratchNumber);
9388
9389 if (!dependency) {
9390 continue;
9391 }
9392 scratchNumber = OSNumber::withNumber(
9393 (unsigned long long)dependency->getLoadTag(),
9394 /* numBits*/ 8 * sizeof(loadTag));
9395 if (!scratchNumber) {
9396 goto finish;
9397 }
9398 dependencyLoadTags->setObject(scratchNumber);
9399 } while (i--);
9400 }
9401 }
9402
9403 OSSafeReleaseNULL(scratchNumber);
9404
9405 /* OSBundleMetaClasses.
9406 */
9407 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleClassesKey)) {
9408 if (metaClasses && metaClasses->getCount()) {
9409 metaClassIterator = OSCollectionIterator::withCollection(metaClasses);
9410 metaClassInfo = OSArray::withCapacity(metaClasses->getCount());
9411 if (!metaClassIterator || !metaClassInfo) {
9412 goto finish;
9413 }
9414 result->setObject(kOSBundleClassesKey, metaClassInfo);
9415
9416 while ((thisMetaClass = OSDynamicCast(OSMetaClass,
9417 metaClassIterator->getNextObject()))) {
9418 OSSafeReleaseNULL(metaClassDict);
9419 OSSafeReleaseNULL(scratchNumber);
9420 OSSafeReleaseNULL(metaClassName);
9421 OSSafeReleaseNULL(superclassName);
9422
9423 metaClassDict = OSDictionary::withCapacity(3);
9424 if (!metaClassDict) {
9425 goto finish;
9426 }
9427
9428 metaClassName = OSString::withCString(thisMetaClass->getClassName());
9429 if (thisMetaClass->getSuperClass()) {
9430 superclassName = OSString::withCString(
9431 thisMetaClass->getSuperClass()->getClassName());
9432 }
9433 scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(),
9434 8 * sizeof(unsigned int));
9435
9436 /* Bail if any of the essentials is missing. The root class lacks a superclass,
9437 * of course.
9438 */
9439 if (!metaClassDict || !metaClassName || !scratchNumber) {
9440 goto finish;
9441 }
9442
9443 metaClassInfo->setObject(metaClassDict);
9444 metaClassDict->setObject(kOSMetaClassNameKey, metaClassName);
9445 if (superclassName) {
9446 metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName);
9447 }
9448 metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber);
9449 }
9450 }
9451 }
9452
9453 /* OSBundleRetainCount.
9454 */
9455 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleRetainCountKey)) {
9456 OSSafeReleaseNULL(scratchNumber);
9457 {
9458 int kextRetainCount = getRetainCount() - 1;
9459 if (isLoaded()) {
9460 kextRetainCount--;
9461 }
9462 scratchNumber = OSNumber::withNumber(
9463 (int)kextRetainCount,
9464 /* numBits*/ 8 * sizeof(int));
9465 if (scratchNumber) {
9466 result->setObject(kOSBundleRetainCountKey, scratchNumber);
9467 }
9468 }
9469 }
9470
9471 success = true;
9472
9473 finish:
9474 OSSafeReleaseNULL(headerData);
9475 OSSafeReleaseNULL(logData);
9476 OSSafeReleaseNULL(cpuTypeNumber);
9477 OSSafeReleaseNULL(cpuSubtypeNumber);
9478 OSSafeReleaseNULL(executablePathString);
9479 if (executablePathCString) {
9480 kfree(executablePathCString, executablePathCStringSize);
9481 }
9482 OSSafeReleaseNULL(scratchNumber);
9483 OSSafeReleaseNULL(dependencyLoadTags);
9484 OSSafeReleaseNULL(metaClassIterator);
9485 OSSafeReleaseNULL(metaClassInfo);
9486 OSSafeReleaseNULL(metaClassDict);
9487 OSSafeReleaseNULL(metaClassName);
9488 OSSafeReleaseNULL(superclassName);
9489 if (!success) {
9490 OSSafeReleaseNULL(result);
9491 }
9492 return result;
9493 }
9494
9495 /*********************************************************************
9496 *********************************************************************/
9497 /* static */
9498 OSReturn
9499 OSKext::requestResource(
9500 const char * kextIdentifierCString,
9501 const char * resourceNameCString,
9502 OSKextRequestResourceCallback callback,
9503 void * context,
9504 OSKextRequestTag * requestTagOut)
9505 {
9506 OSReturn result = kOSReturnError;
9507 OSKext * callbackKext = NULL;// must release (looked up)
9508
9509 OSKextRequestTag requestTag = -1;
9510 OSNumber * requestTagNum = NULL;// must release
9511
9512 OSDictionary * requestDict = NULL;// must release
9513 OSString * kextIdentifier = NULL;// must release
9514 OSString * resourceName = NULL;// must release
9515
9516 OSDictionary * callbackRecord = NULL;// must release
9517 OSData * callbackWrapper = NULL;// must release
9518
9519 OSData * contextWrapper = NULL;// must release
9520
9521 IORecursiveLockLock(sKextLock);
9522
9523 if (requestTagOut) {
9524 *requestTagOut = kOSKextRequestTagInvalid;
9525 }
9526
9527 /* If requests to user space are disabled, don't go any further */
9528 if (!sKernelRequestsEnabled) {
9529 OSKextLog(/* kext */ NULL,
9530 kOSKextLogErrorLevel | kOSKextLogIPCFlag,
9531 "Can't request resource %s for %s - requests to user space are disabled.",
9532 resourceNameCString,
9533 kextIdentifierCString);
9534 result = kOSKextReturnDisabled;
9535 goto finish;
9536 }
9537
9538 if (!kextIdentifierCString || !resourceNameCString || !callback) {
9539 result = kOSKextReturnInvalidArgument;
9540 goto finish;
9541 }
9542
9543 callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
9544 if (!callbackKext) {
9545 OSKextLog(/* kext */ NULL,
9546 kOSKextLogErrorLevel | kOSKextLogIPCFlag,
9547 "Resource request has bad callback address.");
9548 result = kOSKextReturnInvalidArgument;
9549 goto finish;
9550 }
9551 if (!callbackKext->flags.starting && !callbackKext->flags.started) {
9552 OSKextLog(/* kext */ NULL,
9553 kOSKextLogErrorLevel | kOSKextLogIPCFlag,
9554 "Resource request callback is in a kext that is not started.");
9555 result = kOSKextReturnInvalidArgument;
9556 goto finish;
9557 }
9558
9559 /* Do not allow any new requests to be made on a kext that is unloading.
9560 */
9561 if (callbackKext->flags.stopping) {
9562 result = kOSKextReturnStopping;
9563 goto finish;
9564 }
9565
9566 /* If we're wrapped the next available request tag around to the negative
9567 * numbers, we can't service any more requests.
9568 */
9569 if (sNextRequestTag == kOSKextRequestTagInvalid) {
9570 OSKextLog(/* kext */ NULL,
9571 kOSKextLogErrorLevel | kOSKextLogIPCFlag,
9572 "No more request tags available; restart required.");
9573 result = kOSKextReturnNoResources;
9574 goto finish;
9575 }
9576 requestTag = sNextRequestTag++;
9577
9578 result = _OSKextCreateRequest(kKextRequestPredicateRequestResource,
9579 &requestDict);
9580 if (result != kOSReturnSuccess) {
9581 goto finish;
9582 }
9583
9584 kextIdentifier = OSString::withCString(kextIdentifierCString);
9585 resourceName = OSString::withCString(resourceNameCString);
9586 requestTagNum = OSNumber::withNumber((long long unsigned int)requestTag,
9587 8 * sizeof(requestTag));
9588 if (!kextIdentifier ||
9589 !resourceName ||
9590 !requestTagNum ||
9591 !_OSKextSetRequestArgument(requestDict,
9592 kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
9593 !_OSKextSetRequestArgument(requestDict,
9594 kKextRequestArgumentNameKey, resourceName) ||
9595 !_OSKextSetRequestArgument(requestDict,
9596 kKextRequestArgumentRequestTagKey, requestTagNum)) {
9597 result = kOSKextReturnNoMemory;
9598 goto finish;
9599 }
9600
9601 callbackRecord = OSDynamicCast(OSDictionary, requestDict->copyCollection());
9602 if (!callbackRecord) {
9603 result = kOSKextReturnNoMemory;
9604 goto finish;
9605 }
9606 // we validate callback address at call time
9607 callbackWrapper = OSData::withBytes((void *)&callback, sizeof(void *));
9608 if (context) {
9609 contextWrapper = OSData::withBytes((void *)&context, sizeof(void *));
9610 }
9611 if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord,
9612 kKextRequestArgumentCallbackKey, callbackWrapper)) {
9613 result = kOSKextReturnNoMemory;
9614 goto finish;
9615 }
9616
9617 if (context) {
9618 if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord,
9619 kKextRequestArgumentContextKey, contextWrapper)) {
9620 result = kOSKextReturnNoMemory;
9621 goto finish;
9622 }
9623 }
9624
9625 /* Only post the requests after all the other potential failure points
9626 * have been passed.
9627 */
9628 if (!sKernelRequests->setObject(requestDict) ||
9629 !sRequestCallbackRecords->setObject(callbackRecord)) {
9630 result = kOSKextReturnNoMemory;
9631 goto finish;
9632 }
9633
9634 OSKext::pingKextd();
9635
9636 result = kOSReturnSuccess;
9637 if (requestTagOut) {
9638 *requestTagOut = requestTag;
9639 }
9640
9641 finish:
9642
9643 /* If we didn't succeed, yank the request & callback
9644 * from their holding arrays.
9645 */
9646 if (result != kOSReturnSuccess) {
9647 unsigned int index;
9648
9649 index = sKernelRequests->getNextIndexOfObject(requestDict, 0);
9650 if (index != (unsigned int)-1) {
9651 sKernelRequests->removeObject(index);
9652 }
9653 index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord, 0);
9654 if (index != (unsigned int)-1) {
9655 sRequestCallbackRecords->removeObject(index);
9656 }
9657 }
9658
9659 OSKext::considerUnloads(/* rescheduleOnly? */ true);
9660
9661 IORecursiveLockUnlock(sKextLock);
9662
9663 if (callbackKext) {
9664 callbackKext->release();
9665 }
9666 if (requestTagNum) {
9667 requestTagNum->release();
9668 }
9669
9670 if (requestDict) {
9671 requestDict->release();
9672 }
9673 if (kextIdentifier) {
9674 kextIdentifier->release();
9675 }
9676 if (resourceName) {
9677 resourceName->release();
9678 }
9679
9680 if (callbackRecord) {
9681 callbackRecord->release();
9682 }
9683 if (callbackWrapper) {
9684 callbackWrapper->release();
9685 }
9686 if (contextWrapper) {
9687 contextWrapper->release();
9688 }
9689
9690 return result;
9691 }
9692
9693 /*********************************************************************
9694 * Assumes sKextLock is held.
9695 *********************************************************************/
9696 /* static */
9697 OSReturn
9698 OSKext::dequeueCallbackForRequestTag(
9699 OSKextRequestTag requestTag,
9700 OSDictionary ** callbackRecordOut)
9701 {
9702 OSReturn result = kOSReturnError;
9703 OSNumber * requestTagNum = NULL;// must release
9704
9705 requestTagNum = OSNumber::withNumber((long long unsigned int)requestTag,
9706 8 * sizeof(requestTag));
9707 if (!requestTagNum) {
9708 goto finish;
9709 }
9710
9711 result = OSKext::dequeueCallbackForRequestTag(requestTagNum,
9712 callbackRecordOut);
9713
9714 finish:
9715 OSSafeReleaseNULL(requestTagNum);
9716
9717 return result;
9718 }
9719
9720 /*********************************************************************
9721 * Assumes sKextLock is held.
9722 *********************************************************************/
9723 /* static */
9724 OSReturn
9725 OSKext::dequeueCallbackForRequestTag(
9726 OSNumber * requestTagNum,
9727 OSDictionary ** callbackRecordOut)
9728 {
9729 OSReturn result = kOSKextReturnInvalidArgument;
9730 OSDictionary * callbackRecord = NULL;// retain if matched!
9731 OSNumber * callbackTagNum = NULL;// do not release
9732 unsigned int count, i;
9733
9734 result = kOSReturnError;
9735 count = sRequestCallbackRecords->getCount();
9736 for (i = 0; i < count; i++) {
9737 callbackRecord = OSDynamicCast(OSDictionary,
9738 sRequestCallbackRecords->getObject(i));
9739 if (!callbackRecord) {
9740 goto finish;
9741 }
9742
9743 /* If we don't find a tag, we basically have a leak here. Maybe
9744 * we should just remove it.
9745 */
9746 callbackTagNum = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(
9747 callbackRecord, kKextRequestArgumentRequestTagKey));
9748 if (!callbackTagNum) {
9749 goto finish;
9750 }
9751
9752 /* We could be even more paranoid and check that all the incoming
9753 * args match what's in the callback record.
9754 */
9755 if (callbackTagNum->isEqualTo(requestTagNum)) {
9756 if (callbackRecordOut) {
9757 *callbackRecordOut = callbackRecord;
9758 callbackRecord->retain();
9759 }
9760 sRequestCallbackRecords->removeObject(i);
9761 result = kOSReturnSuccess;
9762 goto finish;
9763 }
9764 }
9765 result = kOSKextReturnNotFound;
9766
9767 finish:
9768 return result;
9769 }
9770
9771
9772 /*********************************************************************
9773 * Busy timeout triage
9774 *********************************************************************/
9775 /* static */
9776 bool
9777 OSKext::isWaitingKextd(void)
9778 {
9779 return sRequestCallbackRecords && sRequestCallbackRecords->getCount();
9780 }
9781
9782 /*********************************************************************
9783 * Assumes sKextLock is held.
9784 *********************************************************************/
9785 /* static */
9786 OSReturn
9787 OSKext::dispatchResource(OSDictionary * requestDict)
9788 {
9789 OSReturn result = kOSReturnError;
9790 OSDictionary * callbackRecord = NULL;// must release
9791 OSNumber * requestTag = NULL;// do not release
9792 OSNumber * requestResult = NULL;// do not release
9793 OSData * dataObj = NULL;// do not release
9794 uint32_t dataLength = 0;
9795 const void * dataPtr = NULL;// do not free
9796 OSData * callbackWrapper = NULL;// do not release
9797 OSKextRequestResourceCallback callback = NULL;
9798 OSData * contextWrapper = NULL;// do not release
9799 void * context = NULL;// do not free
9800 OSKext * callbackKext = NULL;// must release (looked up)
9801
9802 /* Get the args from the request. Right now we need the tag
9803 * to look up the callback record, and the result for invoking the callback.
9804 */
9805 requestTag = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
9806 kKextRequestArgumentRequestTagKey));
9807 requestResult = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
9808 kKextRequestArgumentResultKey));
9809 if (!requestTag || !requestResult) {
9810 result = kOSKextReturnInvalidArgument;
9811 goto finish;
9812 }
9813
9814 /* Look for a callback record matching this request's tag.
9815 */
9816 result = dequeueCallbackForRequestTag(requestTag, &callbackRecord);
9817 if (result != kOSReturnSuccess) {
9818 goto finish;
9819 }
9820
9821 /*****
9822 * Get the context pointer of the callback record (if there is one).
9823 */
9824 contextWrapper = OSDynamicCast(OSData, _OSKextGetRequestArgument(callbackRecord,
9825 kKextRequestArgumentContextKey));
9826 context = _OSKextExtractPointer(contextWrapper);
9827 if (contextWrapper && !context) {
9828 goto finish;
9829 }
9830
9831 callbackWrapper = OSDynamicCast(OSData,
9832 _OSKextGetRequestArgument(callbackRecord,
9833 kKextRequestArgumentCallbackKey));
9834 callback = (OSKextRequestResourceCallback)
9835 _OSKextExtractPointer(callbackWrapper);
9836 if (!callback) {
9837 goto finish;
9838 }
9839
9840 /* Check for a data obj. We might not have one and that's ok, that means
9841 * we didn't find the requested resource, and we still have to tell the
9842 * caller that via the callback.
9843 */
9844 dataObj = OSDynamicCast(OSData, _OSKextGetRequestArgument(requestDict,
9845 kKextRequestArgumentValueKey));
9846 if (dataObj) {
9847 dataPtr = dataObj->getBytesNoCopy();
9848 dataLength = dataObj->getLength();
9849 }
9850
9851 callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
9852 if (!callbackKext) {
9853 OSKextLog(/* kext */ NULL,
9854 kOSKextLogErrorLevel | kOSKextLogIPCFlag,
9855 "Can't invoke callback for resource request; ");
9856 goto finish;
9857 }
9858 if (!callbackKext->flags.starting && !callbackKext->flags.started) {
9859 OSKextLog(/* kext */ NULL,
9860 kOSKextLogErrorLevel | kOSKextLogIPCFlag,
9861 "Can't invoke kext resource callback; ");
9862 goto finish;
9863 }
9864
9865 (void)callback(requestTag->unsigned32BitValue(),
9866 (OSReturn)requestResult->unsigned32BitValue(),
9867 dataPtr, dataLength, context);
9868
9869 result = kOSReturnSuccess;
9870
9871 finish:
9872 if (callbackKext) {
9873 callbackKext->release();
9874 }
9875 if (callbackRecord) {
9876 callbackRecord->release();
9877 }
9878
9879 return result;
9880 }
9881
9882 /*********************************************************************
9883 *********************************************************************/
9884 /* static */
9885 void
9886 OSKext::invokeRequestCallback(
9887 OSDictionary * callbackRecord,
9888 OSReturn callbackResult)
9889 {
9890 OSString * predicate = _OSKextGetRequestPredicate(callbackRecord);
9891 OSNumber * resultNum = NULL;// must release
9892
9893 if (!predicate) {
9894 goto finish;
9895 }
9896
9897 resultNum = OSNumber::withNumber((long long unsigned int)callbackResult,
9898 8 * sizeof(callbackResult));
9899 if (!resultNum) {
9900 goto finish;
9901 }
9902
9903 /* Insert the result into the callback record and dispatch it as if it
9904 * were the reply coming down from user space.
9905 */
9906 _OSKextSetRequestArgument(callbackRecord, kKextRequestArgumentResultKey,
9907 resultNum);
9908
9909 if (predicate->isEqualTo(kKextRequestPredicateRequestResource)) {
9910 /* This removes the pending callback record.
9911 */
9912 OSKext::dispatchResource(callbackRecord);
9913 }
9914
9915 finish:
9916 if (resultNum) {
9917 resultNum->release();
9918 }
9919 return;
9920 }
9921
9922 /*********************************************************************
9923 * Assumes sKextLock is held.
9924 *********************************************************************/
9925 /* static */
9926 OSReturn
9927 OSKext::cancelRequest(
9928 OSKextRequestTag requestTag,
9929 void ** contextOut)
9930 {
9931 OSReturn result = kOSKextReturnNoMemory;
9932 OSDictionary * callbackRecord = NULL; // must release
9933 OSData * contextWrapper = NULL;// do not release
9934
9935 IORecursiveLockLock(sKextLock);
9936 result = OSKext::dequeueCallbackForRequestTag(requestTag,
9937 &callbackRecord);
9938 IORecursiveLockUnlock(sKextLock);
9939
9940 if (result == kOSReturnSuccess && contextOut) {
9941 contextWrapper = OSDynamicCast(OSData,
9942 _OSKextGetRequestArgument(callbackRecord,
9943 kKextRequestArgumentContextKey));
9944 *contextOut = _OSKextExtractPointer(contextWrapper);
9945 }
9946
9947 if (callbackRecord) {
9948 callbackRecord->release();
9949 }
9950
9951 return result;
9952 }
9953
9954 /*********************************************************************
9955 * Assumes sKextLock is held.
9956 *********************************************************************/
9957 void
9958 OSKext::invokeOrCancelRequestCallbacks(
9959 OSReturn callbackResult,
9960 bool invokeFlag)
9961 {
9962 unsigned int count, i;
9963
9964 count = sRequestCallbackRecords->getCount();
9965 if (!count) {
9966 goto finish;
9967 }
9968
9969 i = count - 1;
9970 do {
9971 OSDictionary * request = OSDynamicCast(OSDictionary,
9972 sRequestCallbackRecords->getObject(i));
9973
9974 if (!request) {
9975 continue;
9976 }
9977 OSData * callbackWrapper = OSDynamicCast(OSData,
9978 _OSKextGetRequestArgument(request,
9979 kKextRequestArgumentCallbackKey));
9980
9981 if (!callbackWrapper) {
9982 sRequestCallbackRecords->removeObject(i);
9983 continue;
9984 }
9985
9986 vm_address_t callbackAddress = (vm_address_t)
9987 _OSKextExtractPointer(callbackWrapper);
9988
9989 if ((kmod_info->address <= callbackAddress) &&
9990 (callbackAddress < (kmod_info->address + kmod_info->size))) {
9991 if (invokeFlag) {
9992 /* This removes the callback record.
9993 */
9994 invokeRequestCallback(request, callbackResult);
9995 } else {
9996 sRequestCallbackRecords->removeObject(i);
9997 }
9998 }
9999 } while (i--);
10000
10001 finish:
10002 return;
10003 }
10004
10005 /*********************************************************************
10006 * Assumes sKextLock is held.
10007 *********************************************************************/
10008 uint32_t
10009 OSKext::countRequestCallbacks(void)
10010 {
10011 uint32_t result = 0;
10012 unsigned int count, i;
10013
10014 count = sRequestCallbackRecords->getCount();
10015 if (!count) {
10016 goto finish;
10017 }
10018
10019 i = count - 1;
10020 do {
10021 OSDictionary * request = OSDynamicCast(OSDictionary,
10022 sRequestCallbackRecords->getObject(i));
10023
10024 if (!request) {
10025 continue;
10026 }
10027 OSData * callbackWrapper = OSDynamicCast(OSData,
10028 _OSKextGetRequestArgument(request,
10029 kKextRequestArgumentCallbackKey));
10030
10031 if (!callbackWrapper) {
10032 continue;
10033 }
10034
10035 vm_address_t callbackAddress = (vm_address_t)
10036 _OSKextExtractPointer(callbackWrapper);
10037
10038 if ((kmod_info->address <= callbackAddress) &&
10039 (callbackAddress < (kmod_info->address + kmod_info->size))) {
10040 result++;
10041 }
10042 } while (i--);
10043
10044 finish:
10045 return result;
10046 }
10047
10048 /*********************************************************************
10049 *********************************************************************/
10050 static OSReturn
10051 _OSKextCreateRequest(
10052 const char * predicate,
10053 OSDictionary ** requestP)
10054 {
10055 OSReturn result = kOSKextReturnNoMemory;
10056 OSDictionary * request = NULL; // must release on error
10057
10058 request = OSDictionary::withCapacity(2);
10059 if (!request) {
10060 goto finish;
10061 }
10062 result = _OSDictionarySetCStringValue(request,
10063 kKextRequestPredicateKey, predicate);
10064 if (result != kOSReturnSuccess) {
10065 goto finish;
10066 }
10067 result = kOSReturnSuccess;
10068
10069 finish:
10070 if (result != kOSReturnSuccess) {
10071 if (request) {
10072 request->release();
10073 }
10074 } else {
10075 *requestP = request;
10076 }
10077
10078 return result;
10079 }
10080
10081 /*********************************************************************
10082 *********************************************************************/
10083 static OSString *
10084 _OSKextGetRequestPredicate(OSDictionary * requestDict)
10085 {
10086 return OSDynamicCast(OSString,
10087 requestDict->getObject(kKextRequestPredicateKey));
10088 }
10089
10090 /*********************************************************************
10091 *********************************************************************/
10092 static OSObject *
10093 _OSKextGetRequestArgument(
10094 OSDictionary * requestDict,
10095 const char * argName)
10096 {
10097 OSDictionary * args = OSDynamicCast(OSDictionary,
10098 requestDict->getObject(kKextRequestArgumentsKey));
10099 if (args) {
10100 return args->getObject(argName);
10101 }
10102 return NULL;
10103 }
10104
10105 /*********************************************************************
10106 *********************************************************************/
10107 static bool
10108 _OSKextSetRequestArgument(
10109 OSDictionary * requestDict,
10110 const char * argName,
10111 OSObject * value)
10112 {
10113 OSDictionary * args = OSDynamicCast(OSDictionary,
10114 requestDict->getObject(kKextRequestArgumentsKey));
10115 if (!args) {
10116 args = OSDictionary::withCapacity(2);
10117 if (!args) {
10118 goto finish;
10119 }
10120 requestDict->setObject(kKextRequestArgumentsKey, args);
10121 args->release();
10122 }
10123 if (args) {
10124 return args->setObject(argName, value);
10125 }
10126 finish:
10127 return false;
10128 }
10129
10130 /*********************************************************************
10131 *********************************************************************/
10132 static void *
10133 _OSKextExtractPointer(OSData * wrapper)
10134 {
10135 void * result = NULL;
10136 const void * resultPtr = NULL;
10137
10138 if (!wrapper) {
10139 goto finish;
10140 }
10141 resultPtr = wrapper->getBytesNoCopy();
10142 result = *(void **)resultPtr;
10143 finish:
10144 return result;
10145 }
10146
10147 /*********************************************************************
10148 *********************************************************************/
10149 static OSReturn
10150 _OSDictionarySetCStringValue(
10151 OSDictionary * dict,
10152 const char * cKey,
10153 const char * cValue)
10154 {
10155 OSReturn result = kOSKextReturnNoMemory;
10156 const OSSymbol * key = NULL; // must release
10157 OSString * value = NULL; // must release
10158
10159 key = OSSymbol::withCString(cKey);
10160 value = OSString::withCString(cValue);
10161 if (!key || !value) {
10162 goto finish;
10163 }
10164 if (dict->setObject(key, value)) {
10165 result = kOSReturnSuccess;
10166 }
10167
10168 finish:
10169 if (key) {
10170 key->release();
10171 }
10172 if (value) {
10173 value->release();
10174 }
10175
10176 return result;
10177 }
10178
10179 /*********************************************************************
10180 *********************************************************************/
10181 static bool
10182 _OSArrayContainsCString(
10183 OSArray * array,
10184 const char * cString)
10185 {
10186 bool result = false;
10187 const OSSymbol * symbol = NULL;
10188 uint32_t count, i;
10189
10190 if (!array || !cString) {
10191 goto finish;
10192 }
10193
10194 symbol = OSSymbol::withCStringNoCopy(cString);
10195 if (!symbol) {
10196 goto finish;
10197 }
10198
10199 count = array->getCount();
10200 for (i = 0; i < count; i++) {
10201 OSObject * thisObject = array->getObject(i);
10202 if (symbol->isEqualTo(thisObject)) {
10203 result = true;
10204 goto finish;
10205 }
10206 }
10207
10208 finish:
10209 if (symbol) {
10210 symbol->release();
10211 }
10212 return result;
10213 }
10214
10215 /*********************************************************************
10216 * We really only care about boot / system start up related kexts.
10217 * We return true if we're less than REBUILD_MAX_TIME since start up,
10218 * otherwise return false.
10219 *********************************************************************/
10220 bool
10221 _OSKextInPrelinkRebuildWindow(void)
10222 {
10223 static bool outside_the_window = false;
10224 AbsoluteTime my_abstime;
10225 UInt64 my_ns;
10226 SInt32 my_secs;
10227
10228 if (outside_the_window) {
10229 return false;
10230 }
10231 clock_get_uptime(&my_abstime);
10232 absolutetime_to_nanoseconds(my_abstime, &my_ns);
10233 my_secs = (SInt32)(my_ns / NSEC_PER_SEC);
10234 if (my_secs > REBUILD_MAX_TIME) {
10235 outside_the_window = true;
10236 return false;
10237 }
10238 return true;
10239 }
10240
10241 /*********************************************************************
10242 *********************************************************************/
10243 bool
10244 _OSKextInUnloadedPrelinkedKexts( const OSSymbol * theBundleID )
10245 {
10246 int unLoadedCount, i;
10247 bool result = false;
10248
10249 IORecursiveLockLock(sKextLock);
10250
10251 if (sUnloadedPrelinkedKexts == NULL) {
10252 goto finish;
10253 }
10254 unLoadedCount = sUnloadedPrelinkedKexts->getCount();
10255 if (unLoadedCount == 0) {
10256 goto finish;
10257 }
10258
10259 for (i = 0; i < unLoadedCount; i++) {
10260 const OSSymbol * myBundleID;// do not release
10261
10262 myBundleID = OSDynamicCast(OSSymbol, sUnloadedPrelinkedKexts->getObject(i));
10263 if (!myBundleID) {
10264 continue;
10265 }
10266 if (theBundleID->isEqualTo(myBundleID->getCStringNoCopy())) {
10267 result = true;
10268 break;
10269 }
10270 }
10271 finish:
10272 IORecursiveLockUnlock(sKextLock);
10273 return result;
10274 }
10275
10276 #if PRAGMA_MARK
10277 #pragma mark Personalities (IOKit Drivers)
10278 #endif
10279 /*********************************************************************
10280 *********************************************************************/
10281 /* static */
10282 OSArray *
10283 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag)
10284 {
10285 OSArray * result = NULL;// returned
10286 OSCollectionIterator * kextIterator = NULL;// must release
10287 OSArray * personalities = NULL;// must release
10288 OSCollectionIterator * personalitiesIterator = NULL; // must release
10289
10290 OSString * kextID = NULL;// do not release
10291 OSKext * theKext = NULL;// do not release
10292
10293 IORecursiveLockLock(sKextLock);
10294
10295 /* Let's conservatively guess that any given kext has around 3
10296 * personalities for now.
10297 */
10298 result = OSArray::withCapacity(sKextsByID->getCount() * 3);
10299 if (!result) {
10300 goto finish;
10301 }
10302
10303 kextIterator = OSCollectionIterator::withCollection(sKextsByID);
10304 if (!kextIterator) {
10305 goto finish;
10306 }
10307
10308 while ((kextID = OSDynamicCast(OSString, kextIterator->getNextObject()))) {
10309 if (personalitiesIterator) {
10310 personalitiesIterator->release();
10311 personalitiesIterator = NULL;
10312 }
10313 if (personalities) {
10314 personalities->release();
10315 personalities = NULL;
10316 }
10317
10318 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextID));
10319 if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) {
10320 personalities = theKext->copyPersonalitiesArray();
10321 if (!personalities) {
10322 continue;
10323 }
10324 result->merge(personalities);
10325 } else {
10326 // xxx - check for better place to put this log msg
10327 OSKextLog(theKext,
10328 kOSKextLogWarningLevel |
10329 kOSKextLogLoadFlag,
10330 "Kext %s is not loadable during safe boot; "
10331 "omitting its personalities.",
10332 theKext->getIdentifierCString());
10333 }
10334 }
10335
10336 finish:
10337 IORecursiveLockUnlock(sKextLock);
10338
10339 if (kextIterator) {
10340 kextIterator->release();
10341 }
10342 if (personalitiesIterator) {
10343 personalitiesIterator->release();
10344 }
10345 if (personalities) {
10346 personalities->release();
10347 }
10348
10349 return result;
10350 }
10351
10352 /*********************************************************************
10353 *********************************************************************/
10354 /* static */
10355 void
10356 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching)
10357 {
10358 int numPersonalities = 0;
10359
10360 OSKextLog(/* kext */ NULL,
10361 kOSKextLogStepLevel |
10362 kOSKextLogLoadFlag,
10363 "Sending all eligible registered kexts' personalities "
10364 "to the IOCatalogue %s.",
10365 startMatching ? "and starting matching" : "but not starting matching");
10366
10367 OSArray * personalities = OSKext::copyAllKextPersonalities(
10368 /* filterSafeBootFlag */ true);
10369
10370 if (personalities) {
10371 gIOCatalogue->addDrivers(personalities, startMatching);
10372 numPersonalities = personalities->getCount();
10373 personalities->release();
10374 }
10375
10376 OSKextLog(/* kext */ NULL,
10377 kOSKextLogStepLevel |
10378 kOSKextLogLoadFlag,
10379 "%d kext personalit%s sent to the IOCatalogue; %s.",
10380 numPersonalities, numPersonalities > 0 ? "ies" : "y",
10381 startMatching ? "matching started" : "matching not started");
10382 return;
10383 }
10384
10385 /*********************************************************************
10386 * Do not make a deep copy, just convert the IOKitPersonalities dict
10387 * to an array for sending to the IOCatalogue.
10388 *********************************************************************/
10389 OSArray *
10390 OSKext::copyPersonalitiesArray(void)
10391 {
10392 OSArray * result = NULL;
10393 OSDictionary * personalities = NULL;// do not release
10394 OSCollectionIterator * personalitiesIterator = NULL;// must release
10395
10396 OSString * personalityName = NULL;// do not release
10397 OSString * personalityBundleIdentifier = NULL;// do not release
10398
10399 personalities = OSDynamicCast(OSDictionary,
10400 getPropertyForHostArch(kIOKitPersonalitiesKey));
10401 if (!personalities) {
10402 goto finish;
10403 }
10404
10405 result = OSArray::withCapacity(personalities->getCount());
10406 if (!result) {
10407 goto finish;
10408 }
10409
10410 personalitiesIterator =
10411 OSCollectionIterator::withCollection(personalities);
10412 if (!personalitiesIterator) {
10413 goto finish;
10414 }
10415 while ((personalityName = OSDynamicCast(OSString,
10416 personalitiesIterator->getNextObject()))) {
10417 OSDictionary * personality = OSDynamicCast(OSDictionary,
10418 personalities->getObject(personalityName));
10419
10420 /******
10421 * If the personality doesn't have a CFBundleIdentifier, or if it
10422 * differs from the kext's, insert the kext's ID so we can find it.
10423 * The publisher ID is used to remove personalities from bundles
10424 * correctly.
10425 */
10426 personalityBundleIdentifier = OSDynamicCast(OSString,
10427 personality->getObject(kCFBundleIdentifierKey));
10428
10429 if (!personalityBundleIdentifier) {
10430 personality->setObject(kCFBundleIdentifierKey, bundleID);
10431 } else if (!personalityBundleIdentifier->isEqualTo(bundleID)) {
10432 personality->setObject(kIOPersonalityPublisherKey, bundleID);
10433 }
10434
10435 result->setObject(personality);
10436 }
10437
10438 finish:
10439 if (personalitiesIterator) {
10440 personalitiesIterator->release();
10441 }
10442
10443 return result;
10444 }
10445
10446 /*********************************************************************
10447 * Might want to change this to a bool return?
10448 *********************************************************************/
10449 OSReturn
10450 OSKext::sendPersonalitiesToCatalog(
10451 bool startMatching,
10452 OSArray * personalityNames)
10453 {
10454 OSReturn result = kOSReturnSuccess;
10455 OSArray * personalitiesToSend = NULL;// must release
10456 OSDictionary * kextPersonalities = NULL;// do not release
10457 int count, i;
10458
10459 if (!sLoadEnabled) {
10460 OSKextLog(this,
10461 kOSKextLogErrorLevel |
10462 kOSKextLogLoadFlag,
10463 "Kext loading is disabled (attempt to start matching for kext %s).",
10464 getIdentifierCString());
10465 result = kOSKextReturnDisabled;
10466 goto finish;
10467 }
10468
10469 if (sSafeBoot && !isLoadableInSafeBoot()) {
10470 OSKextLog(this,
10471 kOSKextLogErrorLevel |
10472 kOSKextLogLoadFlag,
10473 "Kext %s is not loadable during safe boot; "
10474 "not sending personalities to the IOCatalogue.",
10475 getIdentifierCString());
10476 result = kOSKextReturnNotLoadable;
10477 goto finish;
10478 }
10479
10480 if (!personalityNames || !personalityNames->getCount()) {
10481 personalitiesToSend = copyPersonalitiesArray();
10482 } else {
10483 kextPersonalities = OSDynamicCast(OSDictionary,
10484 getPropertyForHostArch(kIOKitPersonalitiesKey));
10485 if (!kextPersonalities || !kextPersonalities->getCount()) {
10486 // not an error
10487 goto finish;
10488 }
10489 personalitiesToSend = OSArray::withCapacity(0);
10490 if (!personalitiesToSend) {
10491 result = kOSKextReturnNoMemory;
10492 goto finish;
10493 }
10494 count = personalityNames->getCount();
10495 for (i = 0; i < count; i++) {
10496 OSString * name = OSDynamicCast(OSString,
10497 personalityNames->getObject(i));
10498 if (!name) {
10499 continue;
10500 }
10501 OSDictionary * personality = OSDynamicCast(OSDictionary,
10502 kextPersonalities->getObject(name));
10503 if (personality) {
10504 personalitiesToSend->setObject(personality);
10505 }
10506 }
10507 }
10508 if (personalitiesToSend) {
10509 unsigned numPersonalities = personalitiesToSend->getCount();
10510 OSKextLog(this,
10511 kOSKextLogStepLevel |
10512 kOSKextLogLoadFlag,
10513 "Kext %s sending %d personalit%s to the IOCatalogue%s.",
10514 getIdentifierCString(),
10515 numPersonalities,
10516 numPersonalities > 1 ? "ies" : "y",
10517 startMatching ? " and starting matching" : " but not starting matching");
10518 gIOCatalogue->addDrivers(personalitiesToSend, startMatching);
10519 }
10520 finish:
10521 if (personalitiesToSend) {
10522 personalitiesToSend->release();
10523 }
10524 return result;
10525 }
10526
10527 /*********************************************************************
10528 * xxx - We should allow removing the kext's declared personalities,
10529 * xxx - even with other bundle identifiers.
10530 *********************************************************************/
10531 void
10532 OSKext::removePersonalitiesFromCatalog(void)
10533 {
10534 OSDictionary * personality = NULL; // do not release
10535
10536 personality = OSDictionary::withCapacity(1);
10537 if (!personality) {
10538 goto finish;
10539 }
10540 personality->setObject(kCFBundleIdentifierKey, getIdentifier());
10541
10542 OSKextLog(this,
10543 kOSKextLogStepLevel |
10544 kOSKextLogLoadFlag,
10545 "Kext %s removing all personalities naming it from the IOCatalogue.",
10546 getIdentifierCString());
10547
10548 /* Have the IOCatalog remove all personalities matching this kext's
10549 * bundle ID and trigger matching anew.
10550 */
10551 gIOCatalogue->removeDrivers(personality, /* startMatching */ true);
10552
10553 finish:
10554 if (personality) {
10555 personality->release();
10556 }
10557
10558 return;
10559 }
10560
10561
10562 #if PRAGMA_MARK
10563 #pragma mark Logging
10564 #endif
10565 /*********************************************************************
10566 * Do not call any function that takes sKextLock here!
10567 *********************************************************************/
10568 /* static */
10569 OSKextLogSpec
10570 OSKext::setUserSpaceLogFilter(
10571 OSKextLogSpec newUserLogFilter,
10572 bool captureFlag)
10573 {
10574 OSKextLogSpec result;
10575 bool allocError = false;
10576
10577 /* Do not call any function that takes sKextLoggingLock during
10578 * this critical block. That means do logging after.
10579 */
10580 IOLockLock(sKextLoggingLock);
10581
10582 result = sUserSpaceKextLogFilter;
10583 sUserSpaceKextLogFilter = newUserLogFilter;
10584
10585 if (newUserLogFilter && captureFlag &&
10586 !sUserSpaceLogSpecArray && !sUserSpaceLogMessageArray) {
10587 // xxx - do some measurements for a good initial capacity?
10588 sUserSpaceLogSpecArray = OSArray::withCapacity(0);
10589 sUserSpaceLogMessageArray = OSArray::withCapacity(0);
10590
10591 if (!sUserSpaceLogSpecArray || !sUserSpaceLogMessageArray) {
10592 OSSafeReleaseNULL(sUserSpaceLogSpecArray);
10593 OSSafeReleaseNULL(sUserSpaceLogMessageArray);
10594 allocError = true;
10595 }
10596 }
10597
10598 IOLockUnlock(sKextLoggingLock);
10599
10600 /* If the config flag itself is changing, log the state change
10601 * going both ways, before setting up the user-space log arrays,
10602 * so that this is only logged in the kernel.
10603 */
10604 if (result != newUserLogFilter) {
10605 OSKextLog(/* kext */ NULL,
10606 kOSKextLogDebugLevel |
10607 kOSKextLogGeneralFlag,
10608 "User-space log flags changed from 0x%x to 0x%x.",
10609 result, newUserLogFilter);
10610 }
10611 if (allocError) {
10612 OSKextLog(/* kext */ NULL,
10613 kOSKextLogErrorLevel |
10614 kOSKextLogGeneralFlag,
10615 "Failed to allocate user-space log message arrays.");
10616 }
10617
10618 return result;
10619 }
10620
10621 /*********************************************************************
10622 * Do not call any function that takes sKextLock here!
10623 *********************************************************************/
10624 /* static */
10625 OSArray *
10626 OSKext::clearUserSpaceLogFilter(void)
10627 {
10628 OSArray * result = NULL;
10629 OSKextLogSpec oldLogFilter;
10630 OSKextLogSpec newLogFilter = kOSKextLogSilentFilter;
10631
10632 /* Do not call any function that takes sKextLoggingLock during
10633 * this critical block. That means do logging after.
10634 */
10635 IOLockLock(sKextLoggingLock);
10636
10637 result = OSArray::withCapacity(2);
10638 if (result) {
10639 result->setObject(sUserSpaceLogSpecArray);
10640 result->setObject(sUserSpaceLogMessageArray);
10641 }
10642 OSSafeReleaseNULL(sUserSpaceLogSpecArray);
10643 OSSafeReleaseNULL(sUserSpaceLogMessageArray);
10644
10645 oldLogFilter = sUserSpaceKextLogFilter;
10646 sUserSpaceKextLogFilter = newLogFilter;
10647
10648 IOLockUnlock(sKextLoggingLock);
10649
10650 /* If the config flag itself is changing, log the state change
10651 * going both ways, after tearing down the user-space log
10652 * arrays, so this is only logged within the kernel.
10653 */
10654 if (oldLogFilter != newLogFilter) {
10655 OSKextLog(/* kext */ NULL,
10656 kOSKextLogDebugLevel |
10657 kOSKextLogGeneralFlag,
10658 "User-space log flags changed from 0x%x to 0x%x.",
10659 oldLogFilter, newLogFilter);
10660 }
10661
10662 return result;
10663 }
10664
10665
10666 /*********************************************************************
10667 * Do not call any function that takes sKextLock here!
10668 *********************************************************************/
10669 /* static */
10670 OSKextLogSpec
10671 OSKext::getUserSpaceLogFilter(void)
10672 {
10673 OSKextLogSpec result;
10674
10675 IOLockLock(sKextLoggingLock);
10676 result = sUserSpaceKextLogFilter;
10677 IOLockUnlock(sKextLoggingLock);
10678
10679 return result;
10680 }
10681
10682 /*********************************************************************
10683 * This function is called by OSMetaClass during kernel C++ setup.
10684 * Be careful what you access here; assume only OSKext::initialize()
10685 * has been called.
10686 *
10687 * Do not call any function that takes sKextLock here!
10688 *********************************************************************/
10689 #define VTRESET "\033[0m"
10690
10691 #define VTBOLD "\033[1m"
10692 #define VTUNDER "\033[4m"
10693
10694 #define VTRED "\033[31m"
10695 #define VTGREEN "\033[32m"
10696 #define VTYELLOW "\033[33m"
10697 #define VTBLUE "\033[34m"
10698 #define VTMAGENTA "\033[35m"
10699 #define VTCYAN "\033[36m"
10700
10701 inline const char *
10702 colorForFlags(OSKextLogSpec flags)
10703 {
10704 OSKextLogSpec logLevel = flags & kOSKextLogLevelMask;
10705
10706 switch (logLevel) {
10707 case kOSKextLogErrorLevel:
10708 return VTRED VTBOLD;
10709 case kOSKextLogWarningLevel:
10710 return VTRED;
10711 case kOSKextLogBasicLevel:
10712 return VTYELLOW VTUNDER;
10713 case kOSKextLogProgressLevel:
10714 return VTYELLOW;
10715 case kOSKextLogStepLevel:
10716 return VTGREEN;
10717 case kOSKextLogDetailLevel:
10718 return VTCYAN;
10719 case kOSKextLogDebugLevel:
10720 return VTMAGENTA;
10721 default:
10722 return ""; // white
10723 }
10724 }
10725
10726 inline bool
10727 logSpecMatch(
10728 OSKextLogSpec msgLogSpec,
10729 OSKextLogSpec logFilter)
10730 {
10731 OSKextLogSpec filterKextGlobal = logFilter & kOSKextLogKextOrGlobalMask;
10732 OSKextLogSpec filterLevel = logFilter & kOSKextLogLevelMask;
10733 OSKextLogSpec filterFlags = logFilter & kOSKextLogFlagsMask;
10734
10735 OSKextLogSpec msgKextGlobal = msgLogSpec & kOSKextLogKextOrGlobalMask;
10736 OSKextLogSpec msgLevel = msgLogSpec & kOSKextLogLevelMask;
10737 OSKextLogSpec msgFlags = msgLogSpec & kOSKextLogFlagsMask;
10738
10739 /* Explicit messages always get logged.
10740 */
10741 if (msgLevel == kOSKextLogExplicitLevel) {
10742 return true;
10743 }
10744
10745 /* Warnings and errors are logged regardless of the flags.
10746 */
10747 if (msgLevel <= kOSKextLogBasicLevel && (msgLevel <= filterLevel)) {
10748 return true;
10749 }
10750
10751 /* A verbose message that isn't for a logging-enabled kext and isn't global
10752 * does *not* get logged.
10753 */
10754 if (!msgKextGlobal && !filterKextGlobal) {
10755 return false;
10756 }
10757
10758 /* Warnings and errors are logged regardless of the flags.
10759 * All other messages must fit the flags and
10760 * have a level at or below the filter.
10761 *
10762 */
10763 if ((msgFlags & filterFlags) && (msgLevel <= filterLevel)) {
10764 return true;
10765 }
10766 return false;
10767 }
10768
10769 extern "C" {
10770 void
10771 OSKextLog(
10772 OSKext * aKext,
10773 OSKextLogSpec msgLogSpec,
10774 const char * format, ...)
10775 {
10776 va_list argList;
10777
10778 va_start(argList, format);
10779 OSKextVLog(aKext, msgLogSpec, format, argList);
10780 va_end(argList);
10781 }
10782
10783 void
10784 OSKextVLog(
10785 OSKext * aKext,
10786 OSKextLogSpec msgLogSpec,
10787 const char * format,
10788 va_list srcArgList)
10789 {
10790 extern int disableConsoleOutput;
10791
10792 bool logForKernel = false;
10793 bool logForUser = false;
10794 va_list argList;
10795 char stackBuffer[120];
10796 uint32_t length = 0;
10797 char * allocBuffer = NULL; // must kfree
10798 OSNumber * logSpecNum = NULL; // must release
10799 OSString * logString = NULL; // must release
10800 char * buffer = stackBuffer;// do not free
10801
10802 IOLockLock(sKextLoggingLock);
10803
10804 /* Set the kext/global bit in the message spec if we have no
10805 * kext or if the kext requests logging.
10806 */
10807 if (!aKext || aKext->flags.loggingEnabled) {
10808 msgLogSpec = msgLogSpec | kOSKextLogKextOrGlobalMask;
10809 }
10810
10811 logForKernel = logSpecMatch(msgLogSpec, sKernelLogFilter);
10812 if (sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
10813 logForUser = logSpecMatch(msgLogSpec, sUserSpaceKextLogFilter);
10814 }
10815
10816 if (!(logForKernel || logForUser)) {
10817 goto finish;
10818 }
10819
10820 /* No goto from here until past va_end()!
10821 */
10822 va_copy(argList, srcArgList);
10823 length = vsnprintf(stackBuffer, sizeof(stackBuffer), format, argList);
10824 va_end(argList);
10825
10826 if (length + 1 >= sizeof(stackBuffer)) {
10827 allocBuffer = (char *)kalloc_tag((length + 1) * sizeof(char), VM_KERN_MEMORY_OSKEXT);
10828 if (!allocBuffer) {
10829 goto finish;
10830 }
10831
10832 /* No goto from here until past va_end()!
10833 */
10834 va_copy(argList, srcArgList);
10835 vsnprintf(allocBuffer, length + 1, format, argList);
10836 va_end(argList);
10837
10838 buffer = allocBuffer;
10839 }
10840
10841 /* If user space wants the log message, queue it up.
10842 */
10843 if (logForUser && sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
10844 logSpecNum = OSNumber::withNumber(msgLogSpec, 8 * sizeof(msgLogSpec));
10845 logString = OSString::withCString(buffer);
10846 if (logSpecNum && logString) {
10847 sUserSpaceLogSpecArray->setObject(logSpecNum);
10848 sUserSpaceLogMessageArray->setObject(logString);
10849 }
10850 }
10851
10852 /* Always log messages from the kernel according to the kernel's
10853 * log flags.
10854 */
10855 if (logForKernel) {
10856 /* If we are in console mode and have a custom log filter,
10857 * colorize the log message.
10858 */
10859 if (!disableConsoleOutput && sBootArgLogFilterFound) {
10860 const char * color = ""; // do not free
10861 color = colorForFlags(msgLogSpec);
10862 printf("%s%s%s\n", colorForFlags(msgLogSpec),
10863 buffer, color[0] ? VTRESET : "");
10864 } else {
10865 printf("%s\n", buffer);
10866 }
10867 }
10868
10869 finish:
10870 IOLockUnlock(sKextLoggingLock);
10871
10872 if (allocBuffer) {
10873 kfree(allocBuffer, (length + 1) * sizeof(char));
10874 }
10875 OSSafeReleaseNULL(logString);
10876 OSSafeReleaseNULL(logSpecNum);
10877 return;
10878 }
10879
10880 #if KASLR_IOREG_DEBUG
10881
10882 #define IOLOG_INDENT( the_indention ) \
10883 { \
10884 int i; \
10885 for ( i = 0; i < (the_indention); i++ ) { \
10886 IOLog(" "); \
10887 } \
10888 }
10889
10890 extern vm_offset_t vm_kernel_stext;
10891 extern vm_offset_t vm_kernel_etext;
10892 extern mach_vm_offset_t kext_alloc_base;
10893 extern mach_vm_offset_t kext_alloc_max;
10894
10895 bool ScanForAddrInObject(OSObject * theObject,
10896 int indent );
10897
10898 bool
10899 ScanForAddrInObject(OSObject * theObject,
10900 int indent)
10901 {
10902 const OSMetaClass * myTypeID;
10903 OSCollectionIterator * myIter;
10904 OSSymbol * myKey;
10905 OSObject * myValue;
10906 bool myResult = false;
10907
10908 if (theObject == NULL) {
10909 IOLog("%s: theObject is NULL \n",
10910 __FUNCTION__);
10911 return myResult;
10912 }
10913
10914 myTypeID = OSTypeIDInst(theObject);
10915
10916 if (myTypeID == OSTypeID(OSDictionary)) {
10917 OSDictionary * myDictionary;
10918
10919 myDictionary = OSDynamicCast(OSDictionary, theObject);
10920 myIter = OSCollectionIterator::withCollection( myDictionary );
10921 if (myIter == NULL) {
10922 return myResult;
10923 }
10924 myIter->reset();
10925
10926 while ((myKey = OSDynamicCast(OSSymbol, myIter->getNextObject()))) {
10927 bool myTempResult;
10928
10929 myValue = myDictionary->getObject(myKey);
10930 myTempResult = ScanForAddrInObject(myValue, (indent + 4));
10931 if (myTempResult) {
10932 // if we ever get a true result return true
10933 myResult = true;
10934 IOLOG_INDENT(indent);
10935 IOLog("OSDictionary key \"%s\" \n", myKey->getCStringNoCopy());
10936 }
10937 }
10938 myIter->release();
10939 } else if (myTypeID == OSTypeID(OSArray)) {
10940 OSArray * myArray;
10941
10942 myArray = OSDynamicCast(OSArray, theObject);
10943 myIter = OSCollectionIterator::withCollection(myArray);
10944 if (myIter == NULL) {
10945 return myResult;
10946 }
10947 myIter->reset();
10948
10949 while ((myValue = myIter->getNextObject())) {
10950 bool myTempResult;
10951 myTempResult = ScanForAddrInObject(myValue, (indent + 4));
10952 if (myTempResult) {
10953 // if we ever get a true result return true
10954 myResult = true;
10955 IOLOG_INDENT(indent);
10956 IOLog("OSArray: \n");
10957 }
10958 }
10959 myIter->release();
10960 } else if (myTypeID == OSTypeID(OSString) || myTypeID == OSTypeID(OSSymbol)) {
10961 // should we look for addresses in strings?
10962 } else if (myTypeID == OSTypeID(OSData)) {
10963 void * * myPtrPtr;
10964 unsigned int myLen;
10965 OSData * myDataObj;
10966
10967 myDataObj = OSDynamicCast(OSData, theObject);
10968 myPtrPtr = (void * *) myDataObj->getBytesNoCopy();
10969 myLen = myDataObj->getLength();
10970
10971 if (myPtrPtr && myLen && myLen > 7) {
10972 int i;
10973 int myPtrCount = (myLen / sizeof(void *));
10974
10975 for (i = 0; i < myPtrCount; i++) {
10976 UInt64 numberValue = (UInt64) * (myPtrPtr);
10977
10978 if (kext_alloc_max != 0 &&
10979 numberValue >= kext_alloc_base &&
10980 numberValue < kext_alloc_max) {
10981 OSKext * myKext = NULL;// must release (looked up)
10982 // IOLog("found OSData %p in kext map %p to %p \n",
10983 // *(myPtrPtr),
10984 // (void *) kext_alloc_base,
10985 // (void *) kext_alloc_max);
10986
10987 myKext = OSKext::lookupKextWithAddress((vm_address_t) *(myPtrPtr));
10988 if (myKext) {
10989 IOLog("found addr %p from an OSData obj within kext \"%s\" \n",
10990 *(myPtrPtr),
10991 myKext->getIdentifierCString());
10992 myKext->release();
10993 }
10994 myResult = true;
10995 }
10996 if (vm_kernel_etext != 0 &&
10997 numberValue >= vm_kernel_stext &&
10998 numberValue < vm_kernel_etext) {
10999 IOLog("found addr %p from an OSData obj within kernel text segment %p to %p \n",
11000 *(myPtrPtr),
11001 (void *) vm_kernel_stext,
11002 (void *) vm_kernel_etext);
11003 myResult = true;
11004 }
11005 myPtrPtr++;
11006 }
11007 }
11008 } else if (myTypeID == OSTypeID(OSBoolean)) {
11009 // do nothing here...
11010 } else if (myTypeID == OSTypeID(OSNumber)) {
11011 OSNumber * number = OSDynamicCast(OSNumber, theObject);
11012
11013 UInt64 numberValue = number->unsigned64BitValue();
11014
11015 if (kext_alloc_max != 0 &&
11016 numberValue >= kext_alloc_base &&
11017 numberValue < kext_alloc_max) {
11018 OSKext * myKext = NULL;// must release (looked up)
11019 IOLog("found OSNumber in kext map %p to %p \n",
11020 (void *) kext_alloc_base,
11021 (void *) kext_alloc_max);
11022 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
11023
11024 myKext = OSKext::lookupKextWithAddress((vm_address_t) numberValue );
11025 if (myKext) {
11026 IOLog("found in kext \"%s\" \n",
11027 myKext->getIdentifierCString());
11028 myKext->release();
11029 }
11030
11031 myResult = true;
11032 }
11033 if (vm_kernel_etext != 0 &&
11034 numberValue >= vm_kernel_stext &&
11035 numberValue < vm_kernel_etext) {
11036 IOLog("found OSNumber in kernel text segment %p to %p \n",
11037 (void *) vm_kernel_stext,
11038 (void *) vm_kernel_etext);
11039 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
11040 myResult = true;
11041 }
11042 }
11043 #if 0
11044 else {
11045 const OSMetaClass* myMetaClass = NULL;
11046
11047 myMetaClass = theObject->getMetaClass();
11048 if (myMetaClass) {
11049 IOLog("class %s \n", myMetaClass->getClassName());
11050 } else {
11051 IOLog("Unknown object \n" );
11052 }
11053 }
11054 #endif
11055
11056 return myResult;
11057 }
11058 #endif // KASLR_KEXT_DEBUG
11059 }; /* extern "C" */
11060
11061 #if PRAGMA_MARK
11062 #pragma mark Backtrace Dump & kmod_get_info() support
11063 #endif
11064 /*********************************************************************
11065 * This function must be safe to call in panic context.
11066 *********************************************************************/
11067 /* static */
11068 void
11069 OSKext::printKextsInBacktrace(
11070 vm_offset_t * addr __unused,
11071 unsigned int cnt __unused,
11072 int (* printf_func)(const char *fmt, ...) __unused,
11073 uint32_t flags __unused)
11074 {
11075 addr64_t summary_page = 0;
11076 addr64_t last_summary_page = 0;
11077 bool found_kmod = false;
11078 u_int i = 0;
11079
11080 if (kPrintKextsLock & flags) {
11081 if (!sKextSummariesLock) {
11082 return;
11083 }
11084 IOLockLock(sKextSummariesLock);
11085 }
11086
11087 if (!gLoadedKextSummaries) {
11088 (*printf_func)(" can't perform kext scan: no kext summary");
11089 goto finish;
11090 }
11091
11092 summary_page = trunc_page((addr64_t)(uintptr_t)gLoadedKextSummaries);
11093 last_summary_page = round_page(summary_page + sLoadedKextSummariesAllocSize);
11094 for (; summary_page < last_summary_page; summary_page += PAGE_SIZE) {
11095 if (pmap_find_phys(kernel_pmap, summary_page) == 0) {
11096 (*printf_func)(" can't perform kext scan: "
11097 "missing kext summary page %p", summary_page);
11098 goto finish;
11099 }
11100 }
11101
11102 for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
11103 OSKextLoadedKextSummary * summary;
11104
11105 summary = gLoadedKextSummaries->summaries + i;
11106 if (!summary->address) {
11107 continue;
11108 }
11109
11110 if (!summaryIsInBacktrace(summary, addr, cnt)) {
11111 continue;
11112 }
11113
11114 if (!found_kmod) {
11115 if (!(kPrintKextsTerse & flags)) {
11116 (*printf_func)(" Kernel Extensions in backtrace:\n");
11117 }
11118 found_kmod = true;
11119 }
11120
11121 printSummary(summary, printf_func, flags);
11122 }
11123
11124 finish:
11125 if (kPrintKextsLock & flags) {
11126 IOLockUnlock(sKextSummariesLock);
11127 }
11128
11129 return;
11130 }
11131
11132 /*********************************************************************
11133 * This function must be safe to call in panic context.
11134 *********************************************************************/
11135 /* static */
11136 boolean_t
11137 OSKext::summaryIsInBacktrace(
11138 OSKextLoadedKextSummary * summary,
11139 vm_offset_t * addr,
11140 unsigned int cnt)
11141 {
11142 u_int i = 0;
11143
11144 for (i = 0; i < cnt; i++) {
11145 vm_offset_t kscan_addr = addr[i];
11146 if ((kscan_addr >= summary->address) &&
11147 (kscan_addr < (summary->address + summary->size))) {
11148 return TRUE;
11149 }
11150 }
11151
11152 return FALSE;
11153 }
11154
11155 /*
11156 * Get the kext summary object for the kext where 'addr' lies. Must be called with
11157 * sKextSummariesLock held.
11158 */
11159 OSKextLoadedKextSummary *
11160 OSKext::summaryForAddress(const uintptr_t addr)
11161 {
11162 for (unsigned i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
11163 OSKextLoadedKextSummary *summary = &gLoadedKextSummaries->summaries[i];
11164 if (!summary->address) {
11165 continue;
11166 }
11167
11168 #if VM_MAPPED_KEXTS
11169 /* On our platforms that use VM_MAPPED_KEXTS, we currently do not
11170 * support split kexts, but we also may unmap the kexts, which can
11171 * race with the above codepath (see OSKext::unload). As such,
11172 * use a simple range lookup if we are using VM_MAPPED_KEXTS.
11173 */
11174 if ((addr >= summary->address) && (addr < (summary->address + summary->size))) {
11175 return summary;
11176 }
11177 #else
11178 kernel_mach_header_t *mh = (kernel_mach_header_t *)summary->address;
11179 kernel_segment_command_t *seg;
11180
11181 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
11182 if ((addr >= seg->vmaddr) && (addr < (seg->vmaddr + seg->vmsize))) {
11183 return summary;
11184 }
11185 }
11186 #endif
11187 }
11188
11189 /* addr did not map to any kext */
11190 return NULL;
11191 }
11192
11193 /* static */
11194 void *
11195 OSKext::kextForAddress(const void *address)
11196 {
11197 void * image = NULL;
11198 OSKextActiveAccount * active;
11199 OSKext * kext = NULL;
11200 uint32_t baseIdx;
11201 uint32_t lim;
11202 uintptr_t addr = (uintptr_t) address;
11203
11204 if (!addr) {
11205 return NULL;
11206 }
11207
11208 if (sKextAccountsCount) {
11209 IOSimpleLockLock(sKextAccountsLock);
11210 // bsearch sKextAccounts list
11211 for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
11212 active = &sKextAccounts[baseIdx + (lim >> 1)];
11213 if ((addr >= active->address) && (addr < active->address_end)) {
11214 kext = active->account->kext;
11215 if (kext && kext->kmod_info) {
11216 image = (void *) kext->kmod_info->address;
11217 }
11218 break;
11219 } else if (addr > active->address) {
11220 // move right
11221 baseIdx += (lim >> 1) + 1;
11222 lim--;
11223 }
11224 // else move left
11225 }
11226 IOSimpleLockUnlock(sKextAccountsLock);
11227 }
11228 if (!image && (addr >= vm_kernel_stext) && (addr < vm_kernel_etext)) {
11229 image = (void *) &_mh_execute_header;
11230 }
11231
11232 return image;
11233 }
11234
11235 /*********************************************************************
11236 * scan list of loaded kext summaries looking for a load address match and if
11237 * found return the UUID C string. If not found then set empty string.
11238 *********************************************************************/
11239 static void findSummaryUUID(
11240 uint32_t tag_ID,
11241 uuid_string_t uuid);
11242
11243 static void
11244 findSummaryUUID(
11245 uint32_t tag_ID,
11246 uuid_string_t uuid)
11247 {
11248 u_int i;
11249
11250 uuid[0] = 0x00; // default to no UUID
11251
11252 for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
11253 OSKextLoadedKextSummary * summary;
11254
11255 summary = gLoadedKextSummaries->summaries + i;
11256
11257 if (summary->loadTag == tag_ID) {
11258 (void) uuid_unparse(summary->uuid, uuid);
11259 break;
11260 }
11261 }
11262 return;
11263 }
11264
11265 /*********************************************************************
11266 * This function must be safe to call in panic context.
11267 *********************************************************************/
11268 void
11269 OSKext::printSummary(
11270 OSKextLoadedKextSummary * summary,
11271 int (* printf_func)(const char *fmt, ...),
11272 uint32_t flags)
11273 {
11274 kmod_reference_t * kmod_ref = NULL;
11275 uuid_string_t uuid;
11276 char version[kOSKextVersionMaxLength];
11277 uint64_t tmpAddr;
11278
11279 if (!OSKextVersionGetString(summary->version, version, sizeof(version))) {
11280 strlcpy(version, "unknown version", sizeof(version));
11281 }
11282 (void) uuid_unparse(summary->uuid, uuid);
11283
11284 if (kPrintKextsUnslide & flags) {
11285 tmpAddr = ml_static_unslide(summary->address);
11286 } else {
11287 tmpAddr = summary->address;
11288 }
11289 (*printf_func)("%s%s(%s)[%s]@0x%llx->0x%llx\n",
11290 (kPrintKextsTerse & flags) ? "" : " ",
11291 summary->name, version, uuid,
11292 tmpAddr, tmpAddr + summary->size - 1);
11293
11294 if (kPrintKextsTerse & flags) {
11295 return;
11296 }
11297
11298 /* print dependency info */
11299 for (kmod_ref = (kmod_reference_t *) summary->reference_list;
11300 kmod_ref;
11301 kmod_ref = kmod_ref->next) {
11302 kmod_info_t * rinfo;
11303
11304 if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_ref)) == 0) {
11305 (*printf_func)(" kmod dependency scan stopped "
11306 "due to missing dependency page: %p\n",
11307 (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)kmod_ref) : kmod_ref);
11308 break;
11309 }
11310 rinfo = kmod_ref->info;
11311
11312 if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)rinfo)) == 0) {
11313 (*printf_func)(" kmod dependency scan stopped "
11314 "due to missing kmod page: %p\n",
11315 (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)rinfo) : rinfo);
11316 break;
11317 }
11318
11319 if (!rinfo->address) {
11320 continue; // skip fake entries for built-ins
11321 }
11322
11323 /* locate UUID in gLoadedKextSummaries */
11324 findSummaryUUID(rinfo->id, uuid);
11325
11326 if (kPrintKextsUnslide & flags) {
11327 tmpAddr = ml_static_unslide(rinfo->address);
11328 } else {
11329 tmpAddr = rinfo->address;
11330 }
11331 (*printf_func)(" dependency: %s(%s)[%s]@%p\n",
11332 rinfo->name, rinfo->version, uuid, tmpAddr);
11333 }
11334 return;
11335 }
11336
11337
11338 /*******************************************************************************
11339 * substitute() looks at an input string (a pointer within a larger buffer)
11340 * for a match to a substring, and on match it writes the marker & substitution
11341 * character to an output string, updating the scan (from) and
11342 * output (to) indexes as appropriate.
11343 *******************************************************************************/
11344 static int substitute(
11345 const char * scan_string,
11346 char * string_out,
11347 uint32_t * to_index,
11348 uint32_t * from_index,
11349 const char * substring,
11350 char marker,
11351 char substitution);
11352
11353 /* string_out must be at least KMOD_MAX_NAME bytes.
11354 */
11355 static int
11356 substitute(
11357 const char * scan_string,
11358 char * string_out,
11359 uint32_t * to_index,
11360 uint32_t * from_index,
11361 const char * substring,
11362 char marker,
11363 char substitution)
11364 {
11365 uint32_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1);
11366
11367 /* On a substring match, append the marker (if there is one) and then
11368 * the substitution character, updating the output (to) index accordingly.
11369 * Then update the input (from) length by the length of the substring
11370 * that got replaced.
11371 */
11372 if (!strncmp(scan_string, substring, substring_length)) {
11373 if (marker) {
11374 string_out[(*to_index)++] = marker;
11375 }
11376 string_out[(*to_index)++] = substitution;
11377 (*from_index) += substring_length;
11378 return 1;
11379 }
11380 return 0;
11381 }
11382
11383 /*******************************************************************************
11384 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
11385 * KMOD_MAX_NAME characters and performs various substitutions of common
11386 * prefixes & substrings as defined by tables in kext_panic_report.h.
11387 *******************************************************************************/
11388 static void compactIdentifier(
11389 const char * identifier,
11390 char * identifier_out,
11391 char ** identifier_out_end);
11392
11393 static void
11394 compactIdentifier(
11395 const char * identifier,
11396 char * identifier_out,
11397 char ** identifier_out_end)
11398 {
11399 uint32_t from_index, to_index;
11400 uint32_t scan_from_index = 0;
11401 uint32_t scan_to_index = 0;
11402 subs_entry_t * subs_entry = NULL;
11403 int did_sub = 0;
11404
11405 from_index = to_index = 0;
11406 identifier_out[0] = '\0';
11407
11408 /* Replace certain identifier prefixes with shorter @+character sequences.
11409 * Check the return value of substitute() so we only replace the prefix.
11410 */
11411 for (subs_entry = &kext_identifier_prefix_subs[0];
11412 subs_entry->substring && !did_sub;
11413 subs_entry++) {
11414 did_sub = substitute(identifier, identifier_out,
11415 &scan_to_index, &scan_from_index,
11416 subs_entry->substring, /* marker */ '\0', subs_entry->substitute);
11417 }
11418 did_sub = 0;
11419
11420 /* Now scan through the identifier looking for the common substrings
11421 * and replacing them with shorter !+character sequences via substitute().
11422 */
11423 for (/* see above */;
11424 scan_from_index < KMOD_MAX_NAME - 1 && identifier[scan_from_index];
11425 /* see loop */) {
11426 const char * scan_string = &identifier[scan_from_index];
11427
11428 did_sub = 0;
11429
11430 if (scan_from_index) {
11431 for (subs_entry = &kext_identifier_substring_subs[0];
11432 subs_entry->substring && !did_sub;
11433 subs_entry++) {
11434 did_sub = substitute(scan_string, identifier_out,
11435 &scan_to_index, &scan_from_index,
11436 subs_entry->substring, '!', subs_entry->substitute);
11437 }
11438 }
11439
11440 /* If we didn't substitute, copy the input character to the output.
11441 */
11442 if (!did_sub) {
11443 identifier_out[scan_to_index++] = identifier[scan_from_index++];
11444 }
11445 }
11446
11447 identifier_out[scan_to_index] = '\0';
11448 if (identifier_out_end) {
11449 *identifier_out_end = &identifier_out[scan_to_index];
11450 }
11451
11452 return;
11453 }
11454
11455 /*******************************************************************************
11456 * assemble_identifier_and_version() adds to a string buffer a compacted
11457 * bundle identifier followed by a version string.
11458 *******************************************************************************/
11459
11460 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
11461 */
11462 static int assemble_identifier_and_version(
11463 kmod_info_t * kmod_info,
11464 char * identPlusVers,
11465 int bufSize);
11466
11467 static int
11468 assemble_identifier_and_version(
11469 kmod_info_t * kmod_info,
11470 char * identPlusVers,
11471 int bufSize)
11472 {
11473 int result = 0;
11474
11475 compactIdentifier(kmod_info->name, identPlusVers, NULL);
11476 result = strnlen(identPlusVers, KMOD_MAX_NAME - 1);
11477 identPlusVers[result++] = '\t'; // increment for real char
11478 identPlusVers[result] = '\0'; // don't increment for nul char
11479 result = strlcat(identPlusVers, kmod_info->version, bufSize);
11480 if (result >= bufSize) {
11481 identPlusVers[bufSize - 1] = '\0';
11482 result = bufSize - 1;
11483 }
11484
11485 return result;
11486 }
11487
11488 /*******************************************************************************
11489 * Assumes sKextLock is held.
11490 *******************************************************************************/
11491 /* static */
11492 int
11493 OSKext::saveLoadedKextPanicListTyped(
11494 const char * prefix,
11495 int invertFlag,
11496 int libsFlag,
11497 char * paniclist,
11498 uint32_t list_size)
11499 {
11500 int result = -1;
11501 unsigned int count, i;
11502
11503 count = sLoadedKexts->getCount();
11504 if (!count) {
11505 goto finish;
11506 }
11507
11508 i = count - 1;
11509 do {
11510 OSObject * rawKext = sLoadedKexts->getObject(i);
11511 OSKext * theKext = OSDynamicCast(OSKext, rawKext);
11512 int match;
11513 uint32_t identPlusVersLength;
11514 uint32_t tempLen;
11515 char identPlusVers[2 * KMOD_MAX_NAME];
11516
11517 if (!rawKext) {
11518 printf("OSKext::saveLoadedKextPanicListTyped - "
11519 "NULL kext in loaded kext list; continuing\n");
11520 continue;
11521 }
11522
11523 if (!theKext) {
11524 printf("OSKext::saveLoadedKextPanicListTyped - "
11525 "Kext type cast failed in loaded kext list; continuing\n");
11526 continue;
11527 }
11528
11529 /* Skip all built-in kexts.
11530 */
11531 if (theKext->isKernelComponent()) {
11532 continue;
11533 }
11534
11535 kmod_info_t * kmod_info = theKext->kmod_info;
11536
11537 /* Filter for kmod name (bundle identifier).
11538 */
11539 match = !strncmp(kmod_info->name, prefix, strnlen(prefix, KMOD_MAX_NAME));
11540 if ((match && invertFlag) || (!match && !invertFlag)) {
11541 continue;
11542 }
11543
11544 /* Filter for libraries (kexts that have a compatible version).
11545 */
11546 if ((libsFlag == 0 && theKext->getCompatibleVersion() > 1) ||
11547 (libsFlag == 1 && theKext->getCompatibleVersion() < 1)) {
11548 continue;
11549 }
11550
11551 if (!kmod_info ||
11552 !pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_info))) {
11553 printf("kext scan stopped due to missing kmod_info page: %p\n",
11554 kmod_info);
11555 goto finish;
11556 }
11557
11558 identPlusVersLength = assemble_identifier_and_version(kmod_info,
11559 identPlusVers,
11560 sizeof(identPlusVers));
11561 if (!identPlusVersLength) {
11562 printf("error saving loaded kext info\n");
11563 goto finish;
11564 }
11565
11566 /* make sure everything fits and we null terminate.
11567 */
11568 tempLen = strlcat(paniclist, identPlusVers, list_size);
11569 if (tempLen >= list_size) {
11570 // panic list is full, keep it and null terminate
11571 paniclist[list_size - 1] = 0x00;
11572 result = 0;
11573 goto finish;
11574 }
11575 tempLen = strlcat(paniclist, "\n", list_size);
11576 if (tempLen >= list_size) {
11577 // panic list is full, keep it and null terminate
11578 paniclist[list_size - 1] = 0x00;
11579 result = 0;
11580 goto finish;
11581 }
11582 } while (i--);
11583
11584 result = 0;
11585 finish:
11586
11587 return result;
11588 }
11589
11590 /*********************************************************************
11591 *********************************************************************/
11592 /* static */
11593 void
11594 OSKext::saveLoadedKextPanicList(void)
11595 {
11596 char * newlist = NULL;
11597 uint32_t newlist_size = 0;
11598
11599 newlist_size = KEXT_PANICLIST_SIZE;
11600 newlist = (char *)kalloc_tag(newlist_size, VM_KERN_MEMORY_OSKEXT);
11601
11602 if (!newlist) {
11603 OSKextLog(/* kext */ NULL,
11604 kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
11605 "Couldn't allocate kext panic log buffer.");
11606 goto finish;
11607 }
11608
11609 newlist[0] = '\0';
11610
11611 // non-"com.apple." kexts
11612 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
11613 /* libs? */ -1, newlist, newlist_size) != 0) {
11614 goto finish;
11615 }
11616 // "com.apple." nonlibrary kexts
11617 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
11618 /* libs? */ 0, newlist, newlist_size) != 0) {
11619 goto finish;
11620 }
11621 // "com.apple." library kexts
11622 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
11623 /* libs? */ 1, newlist, newlist_size) != 0) {
11624 goto finish;
11625 }
11626
11627 if (loaded_kext_paniclist) {
11628 kfree(loaded_kext_paniclist, loaded_kext_paniclist_size);
11629 }
11630 loaded_kext_paniclist = newlist;
11631 newlist = NULL;
11632 loaded_kext_paniclist_size = newlist_size;
11633
11634 finish:
11635 if (newlist) {
11636 kfree(newlist, newlist_size);
11637 }
11638 return;
11639 }
11640
11641 /*********************************************************************
11642 * Assumes sKextLock is held.
11643 *********************************************************************/
11644 void
11645 OSKext::savePanicString(bool isLoading)
11646 {
11647 u_long len;
11648
11649 if (!kmod_info) {
11650 return; // do not goto finish here b/c of lock
11651 }
11652
11653 len = assemble_identifier_and_version( kmod_info,
11654 (isLoading) ? last_loaded_str_buf : last_unloaded_str_buf,
11655 (isLoading) ? sizeof(last_loaded_str_buf) : sizeof(last_unloaded_str_buf));
11656 if (!len) {
11657 printf("error saving unloaded kext info\n");
11658 goto finish;
11659 }
11660
11661 if (isLoading) {
11662 last_loaded_strlen = len;
11663 last_loaded_address = (void *)kmod_info->address;
11664 last_loaded_size = kmod_info->size;
11665 clock_get_uptime(&last_loaded_timestamp);
11666 } else {
11667 last_unloaded_strlen = len;
11668 last_unloaded_address = (void *)kmod_info->address;
11669 last_unloaded_size = kmod_info->size;
11670 clock_get_uptime(&last_unloaded_timestamp);
11671 }
11672
11673 finish:
11674 return;
11675 }
11676
11677 /*********************************************************************
11678 *********************************************************************/
11679 /* static */
11680 void
11681 OSKext::printKextPanicLists(int (*printf_func)(const char *fmt, ...))
11682 {
11683 if (last_loaded_strlen) {
11684 printf_func("last loaded kext at %llu: %.*s (addr %p, size %lu)\n",
11685 AbsoluteTime_to_scalar(&last_loaded_timestamp),
11686 last_loaded_strlen, last_loaded_str_buf,
11687 last_loaded_address, last_loaded_size);
11688 }
11689
11690 if (last_unloaded_strlen) {
11691 printf_func("last unloaded kext at %llu: %.*s (addr %p, size %lu)\n",
11692 AbsoluteTime_to_scalar(&last_unloaded_timestamp),
11693 last_unloaded_strlen, last_unloaded_str_buf,
11694 last_unloaded_address, last_unloaded_size);
11695 }
11696
11697 printf_func("loaded kexts:\n");
11698 if (loaded_kext_paniclist &&
11699 pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) &&
11700 loaded_kext_paniclist[0]) {
11701 printf_func("%.*s",
11702 strnlen(loaded_kext_paniclist, loaded_kext_paniclist_size),
11703 loaded_kext_paniclist);
11704 } else {
11705 printf_func("(none)\n");
11706 }
11707 return;
11708 }
11709
11710 /*********************************************************************
11711 * Assumes sKextLock is held.
11712 *********************************************************************/
11713 /* static */
11714 void
11715 OSKext::updateLoadedKextSummaries(void)
11716 {
11717 kern_return_t result = KERN_FAILURE;
11718 OSKextLoadedKextSummaryHeader *summaryHeader = NULL;
11719 OSKextLoadedKextSummaryHeader *summaryHeaderAlloc = NULL;
11720 OSKext *aKext;
11721 vm_map_offset_t start, end;
11722 size_t summarySize = 0;
11723 size_t size;
11724 u_int count;
11725 u_int maxKexts;
11726 u_int i, j;
11727 OSKextActiveAccount * accountingList;
11728 OSKextActiveAccount * prevAccountingList;
11729 uint32_t idx, accountingListAlloc, accountingListCount, prevAccountingListCount;
11730
11731 prevAccountingList = NULL;
11732 prevAccountingListCount = 0;
11733
11734 #if DEVELOPMENT || DEBUG
11735 if (IORecursiveLockHaveLock(sKextLock) == false) {
11736 panic("sKextLock must be held");
11737 }
11738 #endif
11739
11740 IOLockLock(sKextSummariesLock);
11741
11742 count = sLoadedKexts->getCount();
11743 for (i = 0, maxKexts = 0; i < count; ++i) {
11744 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
11745 maxKexts += (aKext && aKext->isExecutable());
11746 }
11747
11748 if (!maxKexts) {
11749 goto finish;
11750 }
11751 if (maxKexts < kOSKextTypicalLoadCount) {
11752 maxKexts = kOSKextTypicalLoadCount;
11753 }
11754
11755 /* Calculate the size needed for the new summary headers.
11756 */
11757
11758 size = sizeof(*gLoadedKextSummaries);
11759 size += maxKexts * sizeof(*gLoadedKextSummaries->summaries);
11760 size = round_page(size);
11761
11762 if (gLoadedKextSummaries == NULL || sLoadedKextSummariesAllocSize < size) {
11763 if (gLoadedKextSummaries) {
11764 kmem_free(kernel_map, (vm_offset_t)gLoadedKextSummaries, sLoadedKextSummariesAllocSize);
11765 gLoadedKextSummaries = NULL;
11766 gLoadedKextSummariesTimestamp = mach_absolute_time();
11767 sLoadedKextSummariesAllocSize = 0;
11768 }
11769 result = kmem_alloc(kernel_map, (vm_offset_t *)&summaryHeaderAlloc, size, VM_KERN_MEMORY_OSKEXT);
11770 if (result != KERN_SUCCESS) {
11771 goto finish;
11772 }
11773 summaryHeader = summaryHeaderAlloc;
11774 summarySize = size;
11775 } else {
11776 summaryHeader = gLoadedKextSummaries;
11777 summarySize = sLoadedKextSummariesAllocSize;
11778
11779 start = (vm_map_offset_t) summaryHeader;
11780 end = start + summarySize;
11781 result = vm_map_protect(kernel_map,
11782 start,
11783 end,
11784 VM_PROT_DEFAULT,
11785 FALSE);
11786 if (result != KERN_SUCCESS) {
11787 goto finish;
11788 }
11789 }
11790
11791 /* Populate the summary header.
11792 */
11793
11794 bzero(summaryHeader, summarySize);
11795 summaryHeader->version = kOSKextLoadedKextSummaryVersion;
11796 summaryHeader->entry_size = sizeof(OSKextLoadedKextSummary);
11797
11798 /* Populate each kext summary.
11799 */
11800
11801 count = sLoadedKexts->getCount();
11802 accountingListAlloc = 0;
11803 for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
11804 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
11805 if (!aKext || !aKext->isExecutable()) {
11806 continue;
11807 }
11808
11809 aKext->updateLoadedKextSummary(&summaryHeader->summaries[j++]);
11810 summaryHeader->numSummaries++;
11811 accountingListAlloc++;
11812 }
11813
11814 accountingList = IONew(typeof(accountingList[0]), accountingListAlloc);
11815 accountingListCount = 0;
11816 for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
11817 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
11818 if (!aKext || !aKext->isExecutable()) {
11819 continue;
11820 }
11821
11822 OSKextActiveAccount activeAccount;
11823 aKext->updateActiveAccount(&activeAccount);
11824 // order by address
11825 for (idx = 0; idx < accountingListCount; idx++) {
11826 if (activeAccount.address < accountingList[idx].address) {
11827 break;
11828 }
11829 }
11830 bcopy(&accountingList[idx], &accountingList[idx + 1], (accountingListCount - idx) * sizeof(accountingList[0]));
11831 accountingList[idx] = activeAccount;
11832 accountingListCount++;
11833 }
11834 assert(accountingListCount == accountingListAlloc);
11835 /* Write protect the buffer and move it into place.
11836 */
11837
11838 start = (vm_map_offset_t) summaryHeader;
11839 end = start + summarySize;
11840
11841 result = vm_map_protect(kernel_map, start, end, VM_PROT_READ, FALSE);
11842 if (result != KERN_SUCCESS) {
11843 goto finish;
11844 }
11845
11846 gLoadedKextSummaries = summaryHeader;
11847 gLoadedKextSummariesTimestamp = mach_absolute_time();
11848 sLoadedKextSummariesAllocSize = summarySize;
11849 summaryHeaderAlloc = NULL;
11850
11851 /* Call the magic breakpoint function through a static function pointer so
11852 * the compiler can't optimize the function away.
11853 */
11854 if (sLoadedKextSummariesUpdated) {
11855 (*sLoadedKextSummariesUpdated)();
11856 }
11857
11858 IOSimpleLockLock(sKextAccountsLock);
11859 prevAccountingList = sKextAccounts;
11860 prevAccountingListCount = sKextAccountsCount;
11861 sKextAccounts = accountingList;
11862 sKextAccountsCount = accountingListCount;
11863 IOSimpleLockUnlock(sKextAccountsLock);
11864
11865 finish:
11866 IOLockUnlock(sKextSummariesLock);
11867
11868 /* If we had to allocate a new buffer but failed to generate the summaries,
11869 * free that now.
11870 */
11871 if (summaryHeaderAlloc) {
11872 kmem_free(kernel_map, (vm_offset_t)summaryHeaderAlloc, summarySize);
11873 }
11874 if (prevAccountingList) {
11875 IODelete(prevAccountingList, typeof(accountingList[0]), prevAccountingListCount);
11876 }
11877
11878 return;
11879 }
11880
11881 /*********************************************************************
11882 *********************************************************************/
11883 void
11884 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary *summary)
11885 {
11886 OSData *uuid;
11887
11888 strlcpy(summary->name, getIdentifierCString(),
11889 sizeof(summary->name));
11890
11891 uuid = copyUUID();
11892 if (uuid) {
11893 memcpy(summary->uuid, uuid->getBytesNoCopy(), sizeof(summary->uuid));
11894 OSSafeReleaseNULL(uuid);
11895 }
11896
11897 if (flags.builtin) {
11898 // this value will stop lldb from parsing the mach-o header
11899 // summary->address = UINT64_MAX;
11900 // summary->size = 0;
11901 summary->address = kmod_info->address;
11902 summary->size = kmod_info->size;
11903 } else {
11904 summary->address = kmod_info->address;
11905 summary->size = kmod_info->size;
11906 }
11907 summary->version = getVersion();
11908 summary->loadTag = kmod_info->id;
11909 summary->flags = 0;
11910 summary->reference_list = (uint64_t) kmod_info->reference_list;
11911
11912 return;
11913 }
11914
11915 /*********************************************************************
11916 *********************************************************************/
11917
11918 void
11919 OSKext::updateActiveAccount(OSKextActiveAccount *accountp)
11920 {
11921 kernel_mach_header_t *hdr = NULL;
11922 kernel_segment_command_t *seg = NULL;
11923
11924 bzero(accountp, sizeof(*accountp));
11925
11926 hdr = (kernel_mach_header_t *)kmod_info->address;
11927 if (getcommandfromheader(hdr, LC_SEGMENT_SPLIT_INFO)) {
11928 /* If this kext supports split segments, use the first
11929 * executable segment as the range for instructions
11930 * (and thus for backtracing.
11931 */
11932 for (seg = firstsegfromheader(hdr); seg != NULL; seg = nextsegfromheader(hdr, seg)) {
11933 if (seg->initprot & VM_PROT_EXECUTE) {
11934 break;
11935 }
11936 }
11937 }
11938 if (seg) {
11939 accountp->address = seg->vmaddr;
11940 if (accountp->address) {
11941 accountp->address_end = seg->vmaddr + seg->vmsize;
11942 }
11943 } else {
11944 /* For non-split kexts and for kexts without executable
11945 * segments, just use the kmod_info range (as the kext
11946 * is either all in one range or should not show up in
11947 * instruction backtraces).
11948 */
11949 accountp->address = kmod_info->address;
11950 if (accountp->address) {
11951 accountp->address_end = kmod_info->address + kmod_info->size;
11952 }
11953 }
11954
11955 accountp->account = this->account;
11956 }
11957
11958 extern "C" const vm_allocation_site_t *
11959 OSKextGetAllocationSiteForCaller(uintptr_t address)
11960 {
11961 OSKextActiveAccount * active;
11962 vm_allocation_site_t * site;
11963 vm_allocation_site_t * releasesite;
11964
11965 uint32_t baseIdx;
11966 uint32_t lim;
11967
11968 IOSimpleLockLock(sKextAccountsLock);
11969 site = releasesite = NULL;
11970
11971 // bsearch sKextAccounts list
11972 for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
11973 active = &sKextAccounts[baseIdx + (lim >> 1)];
11974 if ((address >= active->address) && (address < active->address_end)) {
11975 site = &active->account->site;
11976 if (!site->tag) {
11977 vm_tag_alloc_locked(site, &releasesite);
11978 }
11979 break;
11980 } else if (address > active->address) {
11981 // move right
11982 baseIdx += (lim >> 1) + 1;
11983 lim--;
11984 }
11985 // else move left
11986 }
11987 IOSimpleLockUnlock(sKextAccountsLock);
11988 if (releasesite) {
11989 kern_allocation_name_release(releasesite);
11990 }
11991
11992 return site;
11993 }
11994
11995 extern "C" uint32_t
11996 OSKextGetKmodIDForSite(const vm_allocation_site_t * site, char * name, vm_size_t namelen)
11997 {
11998 OSKextAccount * account = (typeof(account))site;
11999 const char * kname;
12000
12001 if (name) {
12002 if (account->kext) {
12003 kname = account->kext->getIdentifierCString();
12004 } else {
12005 kname = "<>";
12006 }
12007 strlcpy(name, kname, namelen);
12008 }
12009
12010 return account->loadTag;
12011 }
12012
12013 extern "C" void
12014 OSKextFreeSite(vm_allocation_site_t * site)
12015 {
12016 OSKextAccount * freeAccount = (typeof(freeAccount))site;
12017 IODelete(freeAccount, OSKextAccount, 1);
12018 }
12019
12020 /*********************************************************************
12021 *********************************************************************/
12022
12023 #if CONFIG_IMAGEBOOT
12024 int
12025 OSKextGetUUIDForName(const char *name, uuid_t uuid)
12026 {
12027 OSKext *kext = OSKext::lookupKextWithIdentifier(name);
12028 if (!kext) {
12029 return 1;
12030 }
12031
12032 OSData *uuid_data = kext->copyUUID();
12033 if (uuid_data) {
12034 memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_t));
12035 OSSafeReleaseNULL(uuid_data);
12036 return 0;
12037 }
12038
12039 return 1;
12040 }
12041 #endif