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