Loading...
--- xnu/xnu-12377.101.15/libkern/c++/OSKext.cpp
+++ xnu/xnu-6153.41.3/libkern/c++/OSKext.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008-2021 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2016 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -26,8 +26,6 @@
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
-#define IOKIT_ENABLE_SHARED_PTR
-
extern "C" {
#include <string.h>
#include <kern/clock.h>
@@ -36,7 +34,7 @@
#include <firehose/tracepoint_private.h>
#include <firehose/chunk_private.h>
#include <os/firehose_buffer_private.h>
-#include <vm/vm_map_xnu.h>
+#include <vm/vm_kern.h>
#include <kextd/kextd_mach.h>
#include <libkern/kernel_mach_header.h>
#include <libkern/kext_panic_report.h>
@@ -48,30 +46,17 @@
#include <mach/host_special_ports.h>
#include <mach/mach_vm.h>
#include <mach/mach_time.h>
+#include <sys/sysctl.h>
#include <uuid/uuid.h>
#include <sys/random.h>
-#include <sys/reboot.h>
-#include <pexpert/pexpert.h>
-#include <pexpert/device_tree.h>
#include <sys/pgo.h>
-
-#if CONFIG_CSR
-#include <sys/csr.h>
-#include <sys/stat.h>
-#include <sys/vnode.h>
-#endif /* CONFIG_CSR */
-};
#if CONFIG_MACF
#include <sys/kauth.h>
#include <security/mac_framework.h>
#endif
-
-#include <vm/vm_kern_xnu.h>
-#include <sys/sysctl.h>
-#include <kern/task.h>
-#include <os/cpp_util.h>
+};
#include <libkern/OSKextLibPrivate.h>
#include <libkern/c++/OSKext.h>
@@ -81,17 +66,11 @@
#include <IOKit/IOCatalogue.h>
#include <IOKit/IORegistryEntry.h>
#include <IOKit/IOService.h>
-#include <IOKit/IOUserServer.h>
#include <IOKit/IOStatisticsPrivate.h>
#include <IOKit/IOBSD.h>
-#include <IOKit/IOPlatformExpert.h>
#include <san/kasan.h>
-
-#if CONFIG_SPTM
-#include <arm64/sptm/sptm.h>
-#endif
#if PRAGMA_MARK
#pragma mark External & Internal Function Protos
@@ -104,66 +83,37 @@
extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); /* osfmk/machine/pmap.h */
extern int dtrace_keep_kernel_symbols(void);
-
-#if defined(__x86_64__) || defined(__i386__)
-extern kern_return_t i386_slide_individual_kext(kernel_mach_header_t *mh, uintptr_t slide);
-extern kern_return_t i386_slide_kext_collection_mh_addrs(kernel_mach_header_t *mh, uintptr_t slide, bool adjust_mach_headers);
-extern void *ubc_getobject_from_filename(const char *filename, struct vnode **, off_t *file_size);
-static void *allocate_kcfileset_map_entry_list(void);
-static void add_kcfileset_map_entry(void *map_entry_list, vm_map_offset_t start, vm_map_offset_t size);
-static void deallocate_kcfileset_map_entry_list_and_unmap_entries(void *map_entry_list, boolean_t unmap_entries, bool pageable);
-int vnode_put(struct vnode *vp);
-kern_return_t vm_map_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size,
- void *control, vm_object_offset_t fileoffset, vm_prot_t max_prot);
-kern_return_t vm_unmap_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size);
-void * ubc_getobject(struct vnode *vp, __unused int flags);
-#endif //(__x86_64__) || defined(__i386__)
}
extern unsigned long gVirtBase;
extern unsigned long gPhysBase;
-
-bool pageableKCloaded = false;
-bool auxKCloaded = false;
-bool resetAuxKCSegmentOnUnload = false;
-
-extern boolean_t pageablekc_uuid_valid;
-extern uuid_t pageablekc_uuid;
-extern uuid_string_t pageablekc_uuid_string;
-
-extern boolean_t auxkc_uuid_valid;
-extern uuid_t auxkc_uuid;
-extern uuid_string_t auxkc_uuid_string;
+#if CONFIG_EMBEDDED
+extern vm_offset_t segLOWESTTEXT;
+#endif /* CONFIG_EMBEDDED */
static OSReturn _OSKextCreateRequest(
const char * predicate,
- OSSharedPtr<OSDictionary> & requestP);
+ OSDictionary ** requestP);
static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict);
static OSObject * _OSKextGetRequestArgument(
OSDictionary * requestDict,
const char * argName);
static bool _OSKextSetRequestArgument(
- OSDictionary * requestDict,
- const char * argName,
- OSMetaClassBase * value);
-template <typename T>
-static T * _OSKextExtractPointer(OSValueObject<T *> * wrapper);
-static OSKextRequestResourceCallback _OSKextExtractCallbackPointer(OSValueObject<OSKextRequestResourceCallback> * wrapper);
+ OSDictionary * requestDict,
+ const char * argName,
+ OSObject * value);
+static void * _OSKextExtractPointer(OSData * wrapper);
static OSReturn _OSDictionarySetCStringValue(
OSDictionary * dict,
const char * key,
const char * value);
+static bool _OSKextInPrelinkRebuildWindow(void);
static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol * theBundleID);
-#if CONFIG_KXLD
-static bool _OSKextInPrelinkRebuildWindow(void);
-#endif
// We really should add containsObject() & containsCString to OSCollection & subclasses.
// So few pad slots, though....
static bool _OSArrayContainsCString(OSArray * array, const char * cString);
static void OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code);
-
-static const char *getDextUniqueIDCString(OSData *dextUniqueID, unsigned int *size);
/* Prelinked arm kexts do not have VM entries because the method we use to
* fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does
@@ -191,7 +141,6 @@
/* Use this number to create containers.
*/
#define kOSKextTypicalLoadCount (150)
-#define kOSKextTypicalUpgradeCount (5)
/* Any kext will have at least 1 retain for the internal lookup-by-ID dict.
* A loaded kext will no dependents or external retains will have 2 retains.
@@ -199,9 +148,6 @@
#define kOSKextMinRetainCount (1)
#define kOSKextMinLoadedRetainCount (2)
-#define kOSKextMaxDextLaunchedCount (~((uint32_t)0))
-#define KOSBundleDextUniqueIdentifierMaxStringLength (KOSBundleDextUniqueIdentifierMaxLength * 2 +1)
-
/**********
* Strings and substrings used in dependency resolution.
*/
@@ -245,11 +191,10 @@
#define _kOSKextExecutableExternalDataKey "_OSKextExecutableExternalData"
#define OS_LOG_HDR_VERSION 1
-#define NUM_OS_LOG_SECTIONS 3
-
-#define OS_LOG_SECT_IDX 0
-#define CSTRING_SECT_IDX 1
-#define ASAN_CSTRING_SECT_IDX 2
+#define NUM_OS_LOG_SECTIONS 2
+
+#define OS_LOG_SECT_IDX 0
+#define CSTRING_SECT_IDX 1
#if PRAGMA_MARK
#pragma mark Typedefs
@@ -298,8 +243,6 @@
static bool sPrelinkBoot = false;
static bool sSafeBoot = false;
static bool sKeepSymbols = false;
-static bool sPanicOnKCMismatch = false;
-static bool sOSKextWasResetAfterUserspaceReboot = false;
/*********************************************************************
* sKextLock is the principal lock for OSKext, and guards all static
@@ -322,31 +265,27 @@
*/
static IORecursiveLock * sKextLock = NULL;
-static OSSharedPtr<OSDictionary> sKextsByID;
-static OSSharedPtr<OSDictionary> sExcludeListByID;
-static OSKextVersion sExcludeListVersion = 0;
-static OSSharedPtr<OSArray> sLoadedKexts;
-static OSSharedPtr<OSDictionary> sNonLoadableKextsByID;
-static OSSharedPtr<OSArray> sUnloadedPrelinkedKexts;
-static OSSharedPtr<OSArray> sLoadedDriverKitKexts;
-static OSSharedPtr<OSDictionary> sDriverKitToUpgradeByID;
-
-// Requests to the IOKit daemon waiting to be picked up.
-static OSSharedPtr<OSArray> sKernelRequests;
+static OSDictionary * sKextsByID = NULL;
+static OSDictionary * sExcludeListByID = NULL;
+static OSKextVersion sExcludeListVersion = 0;
+static OSArray * sLoadedKexts = NULL;
+static OSArray * sUnloadedPrelinkedKexts = NULL;
+static OSArray * sLoadedDriverKitKexts = NULL;
+
+// Requests to kextd waiting to be picked up.
+static OSArray * sKernelRequests = NULL;
// Identifier of kext load requests in sKernelRequests
-static OSSharedPtr<OSSet> sPostedKextLoadIdentifiers;
-static OSSharedPtr<OSArray> sRequestCallbackRecords;
+static OSSet * sPostedKextLoadIdentifiers = NULL;
+static OSArray * sRequestCallbackRecords = NULL;
// Identifiers of all kexts ever requested in kernel; used for prelinked kernel
-static OSSharedPtr<OSSet> sAllKextLoadIdentifiers;
-#if CONFIG_KXLD
+static OSSet * sAllKextLoadIdentifiers = NULL;
static KXLDContext * sKxldContext = NULL;
-#endif
static uint32_t sNextLoadTag = 0;
static uint32_t sNextRequestTag = 0;
static bool sUserLoadsActive = false;
-static bool sIOKitDaemonActive = false;
+static bool sKextdActive = false;
static bool sDeferredLoadSucceeded = false;
static bool sConsiderUnloadsExecuted = false;
@@ -362,16 +301,6 @@
* Stuff for the OSKext representing the kernel itself.
**********/
static OSKext * sKernelKext = NULL;
-
-/* Load Tag IDs used by statically loaded binaries (e.g, the kernel itself). */
-enum : uint32_t {
- kOSKextKernelLoadTag = 0,
-#if CONFIG_SPTM
- kOSKextSPTMLoadTag = 1,
- kOSKextTXMLoadTag = 2,
-#endif /* CONFIG_SPTM */
- kOSKextLoadTagCount
-};
/* Set up a fake kmod_info struct for the kernel.
* It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
@@ -388,7 +317,7 @@
kmod_info_t g_kernel_kmod_info = {
.next = NULL,
.info_version = KMOD_INFO_VERSION,
- .id = kOSKextKernelLoadTag, // loadTag: kernel is always 0
+ .id = 0, // loadTag: kernel is always 0
.name = kOSKextKernelIdentifier,// bundle identifier
.version = "0", // filled in in OSKext::initialize()
.reference_count = -1, // never adjusted; kernel never unloads
@@ -399,39 +328,6 @@
.start = NULL,
.stop = NULL
};
-
-#if CONFIG_SPTM
-/* The SPTM and TXM need fake kmod structures just like the kernel. */
-kmod_info_t g_sptm_kmod_info = {
- .next = NULL,
- .info_version = KMOD_INFO_VERSION,
- .id = kOSKextSPTMLoadTag, // Always one after the kernel
- .name = kOSKextSPTMIdentifier,// bundle identifier
- .version = "0", // filled in by OSKext::initialize()
- .reference_count = -1, // never adjusted; SPTM never unloads
- .reference_list = NULL,
- .address = 0,
- .size = 0, // filled in by OSKext::initialize()
- .hdr_size = 0,
- .start = NULL,
- .stop = NULL
-};
-
-kmod_info_t g_txm_kmod_info = {
- .next = NULL,
- .info_version = KMOD_INFO_VERSION,
- .id = kOSKextTXMLoadTag, // Always one after the SPTM
- .name = kOSKextTXMIdentifier,// bundle identifier
- .version = "0", // filled in by OSKext::initialize()
- .reference_count = -1, // never adjusted; TXM never unloads
- .reference_list = NULL,
- .address = 0,
- .size = 0, // filled in by OSKext::initialize()
- .hdr_size = 0,
- .start = NULL,
- .stop = NULL
-};
-#endif /* CONFIG_SPTM */
/* Set up a fake kmod_info struct for statically linked kexts that don't have one. */
@@ -491,7 +387,7 @@
static kernel_section_t * gBuiltinKmodsSectionInfo;
static kernel_section_t * gBuiltinKmodsSectionStart;
-const OSSymbol * gIOSurfaceIdentifier;
+static const OSSymbol * gIOSurfaceIdentifier;
vm_tag_t gIOSurfaceTag;
/*********************************************************************
@@ -508,17 +404,13 @@
**********/
static IORecursiveLock * sKextInnerLock = NULL;
-#if XNU_TARGET_OS_OSX
static bool sAutounloadEnabled = true;
-#endif
static bool sConsiderUnloadsCalled = false;
static bool sConsiderUnloadsPending = false;
static unsigned int sConsiderUnloadDelay = 60; // seconds
static thread_call_t sUnloadCallout = NULL;
-#if CONFIG_KXLD
static thread_call_t sDestroyLinkContextThread = NULL; // one-shot, one-at-a-time thread
-#endif // CONFIG_KXLD
static bool sSystemSleep = false; // true when system going to sleep
static AbsoluteTime sLastWakeTime; // last time we woke up
@@ -536,49 +428,38 @@
* to automatically parse the list of loaded kexts.
**********/
static IOLock * sKextSummariesLock = NULL;
-extern "C" lck_grp_t vm_page_lck_grp_bucket;
-static lck_grp_t * sKextAccountsLockGrp = &vm_page_lck_grp_bucket;
-#define sKextAccountsLock (&vm_allocation_sites_lock)
+extern "C" lck_spin_t vm_allocation_sites_lock;
+static IOSimpleLock * sKextAccountsLock = &vm_allocation_sites_lock;
void(*const sLoadedKextSummariesUpdated)(void) = OSKextLoadedKextSummariesUpdated;
OSKextLoadedKextSummaryHeader * gLoadedKextSummaries __attribute__((used)) = NULL;
uint64_t gLoadedKextSummariesTimestamp __attribute__((used)) = 0;
static size_t sLoadedKextSummariesAllocSize = 0;
-static OSKextActiveAccount * sKextAccounts;
+static OSKextActiveAccount * sKextAccounts;
static uint32_t sKextAccountsCount;
};
/*********************************************************************
* sKextLoggingLock protects the logging variables declared immediately below.
**********/
-__static_testable IOLock * sKextLoggingLock = NULL;
-
-static const OSKextLogSpec kDefaultKernelLogFilter = kOSKextLogBasicLevel |
+static IOLock * sKextLoggingLock = NULL;
+
+static const OSKextLogSpec kDefaultKernelLogFilter = kOSKextLogBasicLevel |
kOSKextLogVerboseFlagsMask;
-static OSKextLogSpec sKernelLogFilter = kDefaultKernelLogFilter;
-static bool sBootArgLogFilterFound = false;
+static OSKextLogSpec sKernelLogFilter = kDefaultKernelLogFilter;
+static bool sBootArgLogFilterFound = false;
SYSCTL_UINT(_debug, OID_AUTO, kextlog, CTLFLAG_RW | CTLFLAG_LOCKED, &sKernelLogFilter,
0, "kernel kext logging");
-static OSKextLogSpec sUserSpaceKextLogFilter = kOSKextLogSilentFilter;
-static OSSharedPtr<OSArray> sUserSpaceLogSpecArray;
-static OSSharedPtr<OSArray> sUserSpaceLogMessageArray;
+static OSKextLogSpec sUserSpaceKextLogFilter = kOSKextLogSilentFilter;
+static OSArray * sUserSpaceLogSpecArray = NULL;
+static OSArray * sUserSpaceLogMessageArray = NULL;
/*********
* End scope for sKextInnerLock-protected variables.
*********************************************************************/
-/*********************************************************************
- * OSValueObject concrete type instantiations
- **********/
-OSDefineValueObjectForDependentType(void*)
-OSDefineValueObjectForDependentType(OSKextRequestResourceCallback)
-
-
-/**********************************************************************/
-
-TUNABLE(uint32_t, kMaxDextCrashesInOneDay, "daily_max_dext_crashes", kMaxDextCrashesInOneDayDefault);
/*********************************************************************
* helper function used for collecting PGO data upon unload of a kext
@@ -633,7 +514,6 @@
#if PRAGMA_MARK
#pragma mark KXLD Allocation Callback
#endif
-#if CONFIG_KXLD
/*********************************************************************
* KXLD Allocation Callback
*********************************************************************/
@@ -647,19 +527,8 @@
kern_return_t mach_result = KERN_FAILURE;
bool success = false;
OSKext * theKext = (OSKext *)user_data;
- unsigned int roundSize = 0;
- OSSharedPtr<OSData> linkBuffer;
-
- if (round_page(size) > UINT_MAX) {
- OSKextLog(theKext,
- kOSKextLogErrorLevel |
- kOSKextLogGeneralFlag,
- "%s: Requested memory size is greater than UINT_MAX.",
- theKext->getIdentifierCString());
- goto finish;
- }
-
- roundSize = (unsigned int)round_page(size);
+ u_long roundSize = round_page(size);
+ OSData * linkBuffer = NULL;// must release
mach_result = kext_alloc(&result, roundSize, /* fixed */ FALSE);
if (mach_result != KERN_SUCCESS) {
@@ -690,7 +559,7 @@
theKext->getIdentifierCString(),
(void *)result, (unsigned long)roundSize);
- theKext->setLinkedExecutable(linkBuffer.get());
+ theKext->setLinkedExecutable(linkBuffer);
*flags = kKxldAllocateWritable;
success = true;
@@ -700,6 +569,8 @@
kext_free(result, roundSize);
result = 0;
}
+
+ OSSafeReleaseNULL(linkBuffer);
return (kxld_addr_t)result;
}
@@ -749,7 +620,6 @@
OSKextVLog(theKext, logSpec, format, argList);
}
-#endif // CONFIG_KXLD
#if PRAGMA_MARK
#pragma mark IOStatistics defines
@@ -795,184 +665,23 @@
#define super OSObject
OSDefineMetaClassAndStructors(OSKext, OSObject)
-OSDefineMetaClassAndStructors(OSKextSavedMutableSegment, OSObject);
-
-OSDefineMetaClassAndStructors(OSDextStatistics, OSObject);
-
-/*********************************************************************
-*********************************************************************/
-/**
- * Allocate and intialize a fake/representative OSKext object for a statically
- * loaded (by iBoot) binary (e.g., the XNU kernel itself).
- *
- * @param kmod_info Pointer to the kmod_info structure for the binary being
- * setup. At least the "name" and "id" fields needs to already
- * be set correctly.
- *
- * @return The allocated and initialized OSKext object.
- */
-/* static */
-OSKext *
-OSKext::allocAndInitFakeKext(kmod_info_t *kmod_info)
-{
- vm_offset_t load_address = 0;
- const char *bundle_name = NULL;
- bool macho_is_unslid = false;
- bool set_custom_path = false;
- const char *executable_fallback_name = NULL;
-
- if (kmod_info->id == kOSKextKernelLoadTag) {
- load_address = (vm_offset_t)&_mh_execute_header;
- bundle_name = "mach_kernel";
-
- /* The kernel Mach-O header is fixed up to slide all of its addresses. */
- macho_is_unslid = false;
-
- /**
- * No path to the binary is set for the kernel in its OSKext object. The
- * kernel binary is located in fixed directories depending on the OS.
- */
- set_custom_path = false;
- executable_fallback_name = NULL;
-#if CONFIG_SPTM
- } else if (kmod_info->id == kOSKextSPTMLoadTag) {
- load_address = (vm_offset_t)SPTMArgs->debug_header->image[DEBUG_HEADER_ENTRY_SPTM];
- bundle_name = "sptm";
-
- /* The addresses in the SPTM Mach-O header are all unslid. */
- macho_is_unslid = true;
-
- set_custom_path = true;
- executable_fallback_name = "sptm.no.binname.in.macho";
- } else if (kmod_info->id == kOSKextTXMLoadTag) {
- load_address = (vm_offset_t)SPTMArgs->debug_header->image[DEBUG_HEADER_ENTRY_TXM];
- bundle_name = "txm";
-
- /* The addresses in the TXM Mach-O header are all unslid. */
- macho_is_unslid = true;
-
- set_custom_path = true;
- executable_fallback_name = "txm.no.binname.in.macho";
-#endif /* CONFIG_SPTM */
- } else {
- panic("%s: Unsupported kmod_info->id (%d)", __func__, kmod_info->id);
- }
-
- /* Set up an OSKext instance to represent the statically loaded binary. */
- OSKext *fakeKext = new OSKext;
- assert(fakeKext);
- assert(load_address != 0);
-
- /*
- * The start address is always a slid address whereas the last VA returned
- * by getlastaddr() might be unslid depending on the Mach-O. If the address
- * coming from the Mach-O is unslid, then unslide the start address before
- * computing the length of the executable.
- */
- size_t binaryLength = getlastaddr((kernel_mach_header_t*)load_address);
- binaryLength -= (macho_is_unslid) ? ml_static_unslide(load_address) : load_address;
- assert(binaryLength <= UINT_MAX);
-
- /**
- * The load address is always slid. That value will be unslid before being
- * exposed to userspace.
- */
- OSSharedPtr<OSData> executable = OSData::withBytesNoCopy(
- (void*)load_address, (unsigned int)binaryLength);
- assert(executable);
-
- fakeKext->loadTag = sNextLoadTag++;
- fakeKext->bundleID = OSSymbol::withCString(kmod_info->name);
-
- fakeKext->version = OSKextParseVersionString(osrelease);
- fakeKext->compatibleVersion = fakeKext->version;
- fakeKext->linkedExecutable = os::move(executable);
- fakeKext->interfaceUUID = fakeKext->copyUUID();
-
- fakeKext->flags.hasAllDependencies = 1;
- fakeKext->flags.kernelComponent = 1;
- fakeKext->flags.prelinked = 0;
- fakeKext->flags.loaded = 1;
- fakeKext->flags.started = 1;
- fakeKext->flags.CPPInitialized = 0;
- fakeKext->flags.jettisonLinkeditSeg = 0;
- fakeKext->flags.unslidMachO = macho_is_unslid;
-
-#if CONFIG_SPTM
- if (set_custom_path) {
- /* Only SPTM/TXM should have custom paths to their executables set. */
- assert((kmod_info->id == kOSKextSPTMLoadTag) ||
- (kmod_info->id == kOSKextTXMLoadTag));
-
- /* All SPTM/TXM binaries are placed into the same path on internal systems. */
- fakeKext->path = OSString::withCStringNoCopy("/usr/appleinternal/standalone/platform");
-
- /**
- * Each SPTM/TXM Mach-O should contain a __TEXT,__binname section which contains
- * a character array representing the name of the Mach-O executable.
- */
- kernel_section_t *binname_sect =
- getsectbynamefromheader((kernel_mach_header_t*)load_address, "__TEXT", "__binname");
-
- if (binname_sect != NULL) {
- const char *binname = (const char *)ml_static_slide(binname_sect->addr);
- fakeKext->executableRelPath = OSString::withCStringNoCopy(binname);
- } else {
- fakeKext->executableRelPath = OSString::withCStringNoCopy(executable_fallback_name);
- }
- }
-#endif /* CONFIG_SPTM */
-
- fakeKext->kmod_info = kmod_info;
- strlcpy(kmod_info->version, osrelease,
- sizeof(kmod_info->version));
- kmod_info->size = binaryLength;
- assert(kmod_info->id == fakeKext->loadTag);
-
- /*
- * Con up an info dict, so we don't have to have special-case checking all
- * over.
- */
- fakeKext->infoDict = OSDictionary::withCapacity(5);
- assert(fakeKext->infoDict);
- bool setResult = fakeKext->infoDict->setObject(kCFBundleIdentifierKey,
- fakeKext->bundleID.get());
- assert(setResult);
- setResult = fakeKext->infoDict->setObject(kOSKernelResourceKey,
- kOSBooleanTrue);
- assert(setResult);
-
- {
- OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy(osrelease));
- assert(scratchString);
- setResult = fakeKext->infoDict->setObject(kCFBundleVersionKey,
- scratchString.get());
- assert(setResult);
- }
-
- {
- OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy(bundle_name));
- assert(scratchString);
- setResult = fakeKext->infoDict->setObject(kCFBundleNameKey,
- scratchString.get());
- assert(setResult);
- }
-
- return fakeKext;
-}
-
+/*********************************************************************
+*********************************************************************/
/* static */
void
OSKext::initialize(void)
{
- OSSharedPtr<OSData> kernelExecutable = NULL;// do not release
+ OSData * kernelExecutable = NULL;// do not release
+ u_char * kernelStart = NULL;// do not free
+ size_t kernelLength = 0;
+ OSString * scratchString = NULL;// must release
IORegistryEntry * registryRoot = NULL;// do not release
- OSSharedPtr<OSNumber> kernelCPUType;
- OSSharedPtr<OSNumber> kernelCPUSubtype;
+ OSNumber * kernelCPUType = NULL;// must release
+ OSNumber * kernelCPUSubtype = NULL;// must release
OSKextLogSpec bootLogFilter = kOSKextLogSilentFilter;
bool setResult = false;
uint64_t * timestamp = NULL;
- __unused char bootArgBuffer[16];// for PE_parse_boot_argn w/strings
+ char bootArgBuffer[16];// for PE_parse_boot_argn w/strings
/* This must be the first thing allocated. Everything else grabs this lock.
*/
@@ -993,11 +702,9 @@
sPostedKextLoadIdentifiers = OSSet::withCapacity(0);
sAllKextLoadIdentifiers = OSSet::withCapacity(kOSKextTypicalLoadCount);
sRequestCallbackRecords = OSArray::withCapacity(0);
- sDriverKitToUpgradeByID = OSDictionary::withCapacity(kOSKextTypicalUpgradeCount);
-
assert(sKextsByID && sLoadedKexts && sLoadedDriverKitKexts && sKernelRequests &&
sPostedKextLoadIdentifiers && sAllKextLoadIdentifiers &&
- sRequestCallbackRecords && sUnloadedPrelinkedKexts && sDriverKitToUpgradeByID);
+ sRequestCallbackRecords && sUnloadedPrelinkedKexts);
/* Read the log flag boot-args and set the log flags.
*/
@@ -1012,17 +719,8 @@
(unsigned)sKernelLogFilter);
}
-#if !defined(__arm__) && !defined(__arm64__)
- /*
- * On our ARM targets, the kernelcache/boot kernel collection contains
- * the set of kexts required to boot, as specified by KCB. Safeboot is
- * either unsupported, or is supported by the bootloader only loading
- * the boot kernel collection; as a result OSKext has no role to play
- * in safeboot policy on ARM.
- */
sSafeBoot = PE_parse_boot_argn("-x", bootArgBuffer,
sizeof(bootArgBuffer)) ? true : false;
-#endif /* defined(__arm__) && defined(__arm64__) */
if (sSafeBoot) {
OSKextLog(/* kext */ NULL,
@@ -1038,58 +736,88 @@
sKeepSymbols = true;
}
#endif /* CONFIG_DTRACE */
-#if KASAN_DYNAMIC_DENYLIST
+#if KASAN_DYNAMIC_BLACKLIST
/* needed for function lookup */
sKeepSymbols = true;
-#endif /* KASAN_DYNAMIC_DENYLIST */
-
- /*
- * Should we panic when the SystemKC is not linked against the
- * BootKC that was loaded by the booter? By default: yes, if the
- * "-nokcmismatchpanic" boot-arg is passed, then we _don't_ panic
- * on mis-match and instead just print an error and continue.
- */
- sPanicOnKCMismatch = PE_parse_boot_argn("-nokcmismatchpanic", bootArgBuffer,
- sizeof(bootArgBuffer)) ? false : true;
-
- /* Set up an OSKext instance to represent the kernel itself. */
- sKernelKext = allocAndInitFakeKext(&g_kernel_kmod_info);
+#endif
+
+ /* Set up an OSKext instance to represent the kernel itself.
+ */
+ sKernelKext = new OSKext;
assert(sKernelKext);
-#if CONFIG_SPTM
- /* Set up OSKext instances to represent the SPTM/TXM. */
- OSKext *SPTMKext = allocAndInitFakeKext(&g_sptm_kmod_info);
- OSKext *TXMKext = allocAndInitFakeKext(&g_txm_kmod_info);
+ kernelStart = (u_char *)&_mh_execute_header;
+ kernelLength = getlastaddr() - (vm_offset_t)kernelStart;
+ kernelExecutable = OSData::withBytesNoCopy(
+ kernelStart, kernelLength);
+ assert(kernelExecutable);
+
+#if KASLR_KEXT_DEBUG
+ IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu vm_kernel_slide %lu (0x%016lx) \n",
+ (unsigned long)kernelStart,
+ (unsigned long)getlastaddr(),
+ kernelLength,
+ (unsigned long)vm_kernel_slide,
+ (unsigned long)vm_kernel_slide);
#endif
+
+ sKernelKext->loadTag = sNextLoadTag++; // the kernel is load tag 0
+ sKernelKext->bundleID = OSSymbol::withCString(kOSKextKernelIdentifier);
+
+ sKernelKext->version = OSKextParseVersionString(osrelease);
+ sKernelKext->compatibleVersion = sKernelKext->version;
+ sKernelKext->linkedExecutable = kernelExecutable;
+ sKernelKext->interfaceUUID = sKernelKext->copyUUID();
+
+ sKernelKext->flags.hasAllDependencies = 1;
+ sKernelKext->flags.kernelComponent = 1;
+ sKernelKext->flags.prelinked = 0;
+ sKernelKext->flags.loaded = 1;
+ sKernelKext->flags.started = 1;
+ sKernelKext->flags.CPPInitialized = 0;
+ sKernelKext->flags.jettisonLinkeditSeg = 0;
+
+ sKernelKext->kmod_info = &g_kernel_kmod_info;
+ strlcpy(g_kernel_kmod_info.version, osrelease,
+ sizeof(g_kernel_kmod_info.version));
+ g_kernel_kmod_info.size = kernelLength;
+ g_kernel_kmod_info.id = sKernelKext->loadTag;
+
+ /* Cons up an info dict, so we don't have to have special-case
+ * checking all over.
+ */
+ sKernelKext->infoDict = OSDictionary::withCapacity(5);
+ assert(sKernelKext->infoDict);
+ setResult = sKernelKext->infoDict->setObject(kCFBundleIdentifierKey,
+ sKernelKext->bundleID);
+ assert(setResult);
+ setResult = sKernelKext->infoDict->setObject(kOSKernelResourceKey,
+ kOSBooleanTrue);
+ assert(setResult);
+
+ scratchString = OSString::withCStringNoCopy(osrelease);
+ assert(scratchString);
+ setResult = sKernelKext->infoDict->setObject(kCFBundleVersionKey,
+ scratchString);
+ assert(setResult);
+ OSSafeReleaseNULL(scratchString);
+
+ scratchString = OSString::withCStringNoCopy("mach_kernel");
+ assert(scratchString);
+ setResult = sKernelKext->infoDict->setObject(kCFBundleNameKey,
+ scratchString);
+ assert(setResult);
+ OSSafeReleaseNULL(scratchString);
/* Add the kernel kext to the bookkeeping dictionaries. Note that
* the kernel kext doesn't have a kmod_info struct. copyInfo()
* gathers info from other places anyhow.
*/
- setResult = sKextsByID->setObject(sKernelKext->bundleID.get(), sKernelKext);
+ setResult = sKextsByID->setObject(sKernelKext->bundleID, sKernelKext);
assert(setResult);
setResult = sLoadedKexts->setObject(sKernelKext);
assert(setResult);
-
-#if CONFIG_SPTM
- setResult = sKextsByID->setObject(SPTMKext->bundleID.get(), SPTMKext);
- assert(setResult);
- setResult = sLoadedKexts->setObject(SPTMKext);
- assert(setResult);
-
- setResult = sKextsByID->setObject(TXMKext->bundleID.get(), TXMKext);
- assert(setResult);
- setResult = sLoadedKexts->setObject(TXMKext);
- assert(setResult);
-#endif /* CONFIG_SPTM */
-
- // XXX: better way with OSSharedPtr?
- // sKernelKext remains a valid pointer even after the decref
sKernelKext->release();
-#if CONFIG_SPTM
- SPTMKext->release();
- TXMKext->release();
-#endif /* CONFIG_SPTM */
registryRoot = IORegistryEntry::getRegistryRoot();
kernelCPUType = OSNumber::withNumber(
@@ -1100,8 +828,11 @@
8 * sizeof(_mh_execute_header.cpusubtype));
assert(registryRoot && kernelCPUSubtype && kernelCPUType);
- registryRoot->setProperty(kOSKernelCPUTypeKey, kernelCPUType.get());
- registryRoot->setProperty(kOSKernelCPUSubtypeKey, kernelCPUSubtype.get());
+ registryRoot->setProperty(kOSKernelCPUTypeKey, kernelCPUType);
+ registryRoot->setProperty(kOSKernelCPUSubtypeKey, kernelCPUSubtype);
+
+ OSSafeReleaseNULL(kernelCPUType);
+ OSSafeReleaseNULL(kernelCPUSubtype);
gBuiltinKmodsSectionInfo = getsectbyname(kPrelinkInfoSegment, kBuiltinInfoSection);
if (gBuiltinKmodsSectionInfo) {
@@ -1109,24 +840,20 @@
assert(gBuiltinKmodsSectionInfo->addr);
assert(gBuiltinKmodsSectionInfo->size);
- assert(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *) <= UINT_MAX);
- gBuiltinKmodsCount = (unsigned int)(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *));
+ gBuiltinKmodsCount = (gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *));
gBuiltinKmodsSectionStart = getsectbyname(kPrelinkInfoSegment, kBuiltinStartSection);
assert(gBuiltinKmodsSectionStart);
assert(gBuiltinKmodsSectionStart->addr);
assert(gBuiltinKmodsSectionStart->size);
- assert(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t) <= UINT_MAX);
- count = (unsigned int)(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t));
+ count = (gBuiltinKmodsSectionStart->size / sizeof(uintptr_t));
// one extra pointer for the end of last kmod
assert(count == (gBuiltinKmodsCount + 1));
vm_kernel_builtinkmod_text = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[0];
vm_kernel_builtinkmod_text_end = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[count - 1];
}
-
- // Don't track this object -- it's never released
- gIOSurfaceIdentifier = OSSymbol::withCStringNoCopy("com.apple.iokit.IOSurface").detach();
+ gIOSurfaceIdentifier = OSSymbol::withCStringNoCopy("com.apple.iokit.IOSurface");
timestamp = __OSAbsoluteTimePtr(&last_loaded_timestamp);
*timestamp = 0;
@@ -1141,10 +868,6 @@
"Kext system initialized.");
notifyKextLoadObservers(sKernelKext, sKernelKext->kmod_info);
-#if CONFIG_SPTM
- notifyKextLoadObservers(SPTMKext, SPTMKext->kmod_info);
- notifyKextLoadObservers(TXMKext, TXMKext->kmod_info);
-#endif
return;
}
@@ -1167,30 +890,18 @@
int dt_symtab_size = 0;
int dt_result = 0;
- kernel_segment_command_t * seg_kld = NULL;
- kernel_segment_command_t * seg_klddata = NULL;
- kernel_segment_command_t * seg_linkedit = NULL;
-
- const char __unused * dt_segment_name = NULL;
- void __unused * segment_paddress = NULL;
- int __unused segment_size = 0;
+ kernel_segment_command_t * seg_to_remove = NULL;
+
+#if __arm__ || __arm64__
+ const char * dt_segment_name = NULL;
+ void * segment_paddress = NULL;
+ int segment_size = 0;
+#endif
OSKextLog(/* kext */ NULL,
kOSKextLogProgressLevel |
kOSKextLogGeneralFlag,
"Jettisoning kext bootstrap segments.");
-
- /*
- * keep the linkedit segment around when booted from a new MH_FILESET
- * KC because all the kexts shared a linkedit segment.
- */
- kc_format_t kc_format;
- if (!PE_get_primary_kc_format(&kc_format)) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel |
- kOSKextLogGeneralFlag,
- "Unable to determine primary KC format");
- }
/*****
* Dispose of unnecessary stuff that the booter didn't need to load.
@@ -1209,94 +920,66 @@
}
/*****
- * KLD & KLDDATA bootstrap segments.
+ * KLD bootstrap segment.
*/
// xxx - should rename KLD segment
- seg_kld = getsegbyname("__KLD");
- seg_klddata = getsegbyname("__KLDDATA");
- if (seg_klddata) {
- // __mod_term_func is part of __KLDDATA
- OSRuntimeUnloadCPPForSegment(seg_klddata);
+ seg_to_remove = getsegbyname("__KLD");
+ if (seg_to_remove) {
+ OSRuntimeUnloadCPPForSegment(seg_to_remove);
}
#if __arm__ || __arm64__
- /* Free the memory that was set up by iBoot.
- */
-#if !defined(KERNEL_INTEGRITY_KTRR) && !defined(KERNEL_INTEGRITY_CTRR) && !defined(KERNEL_INTEGRITY_PV_CTRR)
- /* We cannot free the KLD segment with CTRR enabled as it contains text and
- * is covered by the contiguous rorgn.
+ /* Free the memory that was set up by bootx.
*/
dt_segment_name = "Kernel-__KLD";
if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
+ /* We cannot free this with KTRR enabled, as we cannot
+ * update the permissions on the KLD range this late
+ * in the boot process.
+ */
IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
- (int)segment_size); // calls ml_static_mfree
- } else if (seg_kld && seg_kld->vmaddr && seg_kld->vmsize) {
- /* With fileset KCs, the Kernel KLD segment is not recorded in the DT. */
-#if !CONFIG_SPTM
- ml_static_mfree(ml_static_ptovirt(seg_kld->vmaddr - gVirtBase + gPhysBase),
- seg_kld->vmsize);
-#else
- ml_static_mfree(seg_kld->vmaddr, seg_kld->vmsize);
-#endif
- }
-#endif
- dt_segment_name = "Kernel-__KLDDATA";
- if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
- IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
- (int)segment_size); // calls ml_static_mfree
- } else if (seg_klddata && seg_klddata->vmaddr && seg_klddata->vmsize) {
- /* With fileset KCs, the Kernel KLDDATA segment is not recorded in the DT. */
-#if !CONFIG_SPTM
- ml_static_mfree(ml_static_ptovirt(seg_klddata->vmaddr - gVirtBase + gPhysBase),
- seg_klddata->vmsize);
-#else
- ml_static_mfree(seg_klddata->vmaddr, seg_klddata->vmsize);
-#endif
+ (int)segment_size);
}
#elif __i386__ || __x86_64__
/* On x86, use the mapping data from the segment load command to
- * unload KLD & KLDDATA directly.
+ * unload KLD directly.
* This may invalidate any assumptions about "avail_start"
* defining the lower bound for valid physical addresses.
*/
- if (seg_kld && seg_kld->vmaddr && seg_kld->vmsize) {
- bzero((void *)seg_kld->vmaddr, seg_kld->vmsize);
- ml_static_mfree(seg_kld->vmaddr, seg_kld->vmsize);
- }
- if (seg_klddata && seg_klddata->vmaddr && seg_klddata->vmsize) {
- bzero((void *)seg_klddata->vmaddr, seg_klddata->vmsize);
- ml_static_mfree(seg_klddata->vmaddr, seg_klddata->vmsize);
+ if (seg_to_remove && seg_to_remove->vmaddr && seg_to_remove->vmsize) {
+ // 04/18/11 - gab: <rdar://problem/9236163>
+ // overwrite memory occupied by KLD segment with random data before
+ // releasing it.
+ read_frandom((void *) seg_to_remove->vmaddr, seg_to_remove->vmsize);
+ ml_static_mfree(seg_to_remove->vmaddr, seg_to_remove->vmsize);
}
#else
#error arch
#endif
+ seg_to_remove = NULL;
+
/*****
* Prelinked kernel's symtab (if there is one).
*/
- if (kc_format != KCFormatFileset) {
- kernel_section_t * sect;
- sect = getsectbyname("__PRELINK", "__symtab");
- if (sect && sect->addr && sect->size) {
- ml_static_mfree(sect->addr, sect->size);
- }
- }
-
- seg_linkedit = (kernel_segment_command_t *)getsegbyname("__LINKEDIT");
+ kernel_section_t * sect;
+ sect = getsectbyname("__PRELINK", "__symtab");
+ if (sect && sect->addr && sect->size) {
+ ml_static_mfree(sect->addr, sect->size);
+ }
+
+ seg_to_remove = (kernel_segment_command_t *)getsegbyname("__LINKEDIT");
/* kxld always needs the kernel's __LINKEDIT segment, but we can make it
* pageable, unless keepsyms is set. To do that, we have to copy it from
* its booter-allocated memory, free the booter memory, reallocate proper
* managed memory, then copy the segment back in.
- *
- * NOTE: This optimization is not valid for fileset KCs because each
- * fileset entry (kext or xnu) in an MH_FILESET has a LINKEDIT segment
- * that points to one fileset-global LINKEDIT segment. This
- * optimization is also only valid for platforms that support vm
- * mapped kexts or mapped kext collections (pageable KCs)
- */
-#if VM_MAPPED_KEXTS
- if (!sKeepSymbols && kc_format != KCFormatFileset) {
+ */
+#if CONFIG_KXLD
+#if (__arm__ || __arm64__)
+#error CONFIG_KXLD not expected for this arch
+#endif
+ if (!sKeepSymbols) {
kern_return_t mem_result;
void *seg_copy = NULL;
void *seg_data = NULL;
@@ -1304,14 +987,14 @@
vm_map_offset_t seg_copy_offset = 0;
vm_map_size_t seg_length = 0;
- seg_data = (void *) seg_linkedit->vmaddr;
- seg_offset = (vm_map_offset_t) seg_linkedit->vmaddr;
- seg_length = (vm_map_size_t) seg_linkedit->vmsize;
+ seg_data = (void *) seg_to_remove->vmaddr;
+ seg_offset = (vm_map_offset_t) seg_to_remove->vmaddr;
+ seg_length = (vm_map_size_t) seg_to_remove->vmsize;
/* Allocate space for the LINKEDIT copy.
*/
mem_result = kmem_alloc(kernel_map, (vm_offset_t *) &seg_copy,
- seg_length, KMA_ZERO, VM_KERN_MEMORY_KEXT);
+ seg_length, VM_KERN_MEMORY_KEXT);
if (mem_result != KERN_SUCCESS) {
OSKextLog(/* kext */ NULL,
kOSKextLogErrorLevel |
@@ -1331,11 +1014,13 @@
/* Set up the VM region.
*/
- mem_result = mach_vm_map_kernel(
+ mem_result = vm_map_enter_mem_object(
kernel_map,
&seg_offset,
seg_length, /* mask */ 0,
- VM_MAP_KERNEL_FLAGS_FIXED(.vmf_overwrite = true),
+ VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE,
+ VM_MAP_KERNEL_FLAGS_NONE,
+ VM_KERN_MEMORY_NONE,
(ipc_port_t)NULL,
(vm_object_offset_t) 0,
/* copy */ FALSE,
@@ -1359,16 +1044,16 @@
/* Free the copy.
*/
kmem_free(kernel_map, seg_copy_offset, seg_length);
- } else if (!sKeepSymbols && kc_format == KCFormatFileset) {
- /* Remove the linkedit segment of the Boot KC */
- kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary);
- OSKext::jettisonFileSetLinkeditSegment(mh);
- }
-#else // !VM_MAPPED_KEXTS
+ }
+#else /* we are not CONFIG_KXLD */
+#if !(__arm__ || __arm64__)
+#error CONFIG_KXLD is expected for this arch
+#endif
+
/*****
* Dump the LINKEDIT segment, unless keepsyms is set.
*/
- if (!sKeepSymbols && kc_format != KCFormatFileset) {
+ if (!sKeepSymbols) {
dt_segment_name = "Kernel-__LINKEDIT";
if (0 == IODTGetLoaderInfo(dt_segment_name,
&segment_paddress, &segment_size)) {
@@ -1379,39 +1064,28 @@
IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
(int)segment_size);
}
- } else if (!sKeepSymbols && kc_format == KCFormatFileset) {
- /* Remove the linkedit segment of the Boot KC */
- kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary);
- OSKext::jettisonFileSetLinkeditSegment(mh);
} else {
OSKextLog(/* kext */ NULL,
kOSKextLogBasicLevel |
kOSKextLogGeneralFlag,
"keepsyms boot arg specified; keeping linkedit segment for symbols.");
}
-#endif // VM_MAPPED_KEXTS
+#endif /* CONFIG_KXLD */
+
+ seg_to_remove = NULL;
result = kOSReturnSuccess;
return result;
}
-#if CONFIG_KXLD
/*********************************************************************
*********************************************************************/
void
OSKext::flushNonloadedKexts(
Boolean flushPrelinkedKexts)
{
- OSSharedPtr<OSSet> keepKexts;
-
- /* TODO: make this more efficient with MH_FILESET kexts */
-
- // Do not unload prelinked kexts on arm because the kernelcache is not
- // structured in a way that allows them to be unmapped
-#if !defined(__x86_64__)
- flushPrelinkedKexts = false;
-#endif /* defined(__x86_64__) */
+ OSSet * keepKexts = NULL;// must release
IORecursiveLockLock(sKextLock);
@@ -1434,31 +1108,28 @@
* any lingering inter-kext references for nonloaded kexts
* so they have min. retain counts.
*/
- {
- sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) {
- OSKext * thisKext = OSDynamicCast(OSKext, obj);
- if (!thisKext) {
- return false;
- }
- if (!flushPrelinkedKexts && thisKext->isPrelinked()) {
- keepKexts->setObject(thisKext);
- } else if (!thisKext->declaresExecutable()) {
- /*
- * Don't unload codeless kexts, because they never appear in the loadedKexts array.
- * Requesting one from the IOKit daemon will load it and then immediately remove it by calling
- * flushNonloadedKexts().
- * And adding one to loadedKexts breaks code assuming they have kmod_info etc.
- */
- keepKexts->setObject(thisKext);
- } else if (thisKext->isInFileset()) {
- /* keep all kexts in the new MH_FILESET KC */
- keepKexts->setObject(thisKext);
- }
-
- thisKext->flushDependencies(/* forceIfLoaded */ false);
- return false;
- });
- }
+ sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) {
+ OSKext * thisKext = OSDynamicCast(OSKext, obj);
+ if (!thisKext) {
+ return false;
+ }
+ if (!flushPrelinkedKexts && thisKext->isPrelinked()) {
+ keepKexts->setObject(thisKext);
+ }
+ if (!thisKext->declaresExecutable()) {
+ /*
+ * Don't unload codeless kexts, because they never appear in the loadedKexts array.
+ * Requesting one from kextd will load it and then immediately remove it by calling
+ * flushNonloadedKexts().
+ * And adding one to loadedKexts breaks code assuming they have kmod_info etc.
+ */
+ keepKexts->setObject(thisKext);
+ }
+
+ thisKext->flushDependencies(/* forceIfLoaded */ false);
+ return false;
+ });
+
/* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
*/
sKextsByID->flushCollection();
@@ -1487,55 +1158,22 @@
finish:
IORecursiveLockUnlock(sKextLock);
+
+ OSSafeReleaseNULL(keepKexts);
+
return;
}
-#else /* !CONFIG_KXLD */
-
-void
-OSKext::flushNonloadedKexts(
- Boolean flushPrelinkedKexts __unused)
-{
- IORecursiveLockLock(sKextLock);
-
- OSKextLog(/* kext */ NULL,
- kOSKextLogProgressLevel |
- kOSKextLogKextBookkeepingFlag,
- "Flushing dependency info for non-loaded kexts.");
-
- /*
- * In a world where we don't dynamically link kexts, they all come
- * from a kext collection that's either in wired memory, or
- * wire-on-demand. We don't need to mess around with moving kexts in
- * and out of the sKextsByID array - they can all just stay there.
- * Here we just flush the dependency list for kexts that are not
- * loaded.
- */
- sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) {
- OSKext * thisKext = OSDynamicCast(OSKext, obj);
- if (!thisKext) {
- return false;
- }
- thisKext->flushDependencies(/* forceIfLoaded */ false);
- return false;
- });
-
- IORecursiveLockUnlock(sKextLock);
- return;
-}
-
-#endif /* CONFIG_KXLD */
/*********************************************************************
*********************************************************************/
/* static */
void
-OSKext::setIOKitDaemonActive(bool active)
-{
- IOServiceTrace(IOSERVICE_KEXTD_ALIVE, 0, 0, 0, 0);
+OSKext::setKextdActive(Boolean active)
+{
IORecursiveLockLock(sKextLock);
- sIOKitDaemonActive = active;
+ sKextdActive = active;
if (sKernelRequests->getCount()) {
- OSKext::pingIOKitDaemon();
+ OSKext::pingKextd();
}
IORecursiveLockUnlock(sKextLock);
@@ -1552,13 +1190,13 @@
/* static */
OSReturn
-OSKext::pingIOKitDaemon(void)
+OSKext::pingKextd(void)
{
OSReturn result = kOSReturnError;
#if !NO_KEXTD
mach_port_t kextd_port = IPC_PORT_NULL;
- if (!sIOKitDaemonActive) {
+ if (!sKextdActive) {
result = kOSKextReturnDisabled; // basically unavailable
goto finish;
}
@@ -1568,7 +1206,7 @@
OSKextLog(/* kext */ NULL,
kOSKextLogErrorLevel |
kOSKextLogIPCFlag,
- "Can't get " kIOKitDaemonName " port.");
+ "Can't get kextd port.");
goto finish;
}
@@ -1577,7 +1215,7 @@
OSKextLog(/* kext */ NULL,
kOSKextLogErrorLevel |
kOSKextLogIPCFlag,
- kIOKitDaemonName " ping failed (0x%x).", (int)result);
+ "kextd ping failed (0x%x).", (int)result);
goto finish;
}
@@ -1593,49 +1231,6 @@
/*********************************************************************
*********************************************************************/
/* static */
-
-bool
-OSKext::driverkitEnabled(void)
-{
- #if XNU_TARGET_OS_WATCH
- /*
- * Driverkit support is available on watchOS only if the device
- * tree has the "supports-driverkit" property in its "/product" node
- */
- DTEntry entry;
- void const *prop = NULL;
- unsigned int prop_size;
-
- if (kSuccess != SecureDTLookupEntry(NULL, "/product", &entry)) {
- return false;
- }
- if (kSuccess != SecureDTGetProperty(entry, "supports-driverkit", &prop, &prop_size)) {
- return false;
- }
- #endif /* XNU_TARGET_OS_WATCH */
-
- return true;
-}
-
-/*********************************************************************
-*********************************************************************/
-/* static */
-bool
-OSKext::iokitDaemonAvailable(void)
-{
-#if XNU_TARGET_OS_XR || XNU_TARGET_OS_BRIDGE
- int notused;
- if (PE_parse_boot_argn("-restore", ¬used, sizeof(notused))) {
- return false;
- }
-#endif /* XNU_TARGET_OS_XR || XNU_TARGET_OS_BRIDGE */
-
- return driverkitEnabled();
-}
-
-/*********************************************************************
-*********************************************************************/
-/* static */
void
OSKext::setDeferredLoadSucceeded(Boolean succeeded)
{
@@ -1656,7 +1251,7 @@
#if !NO_KEXTD
OSReturn checkResult = kOSReturnError;
#endif
- OSSharedPtr<OSDictionary> exitRequest;
+ OSDictionary * exitRequest = NULL; // must release
IORecursiveLockLock(sKextLock);
@@ -1665,102 +1260,30 @@
OSKext::setAutounloadsEnabled(false);
OSKext::setKernelRequestsEnabled(false);
-#if defined(__x86_64__) || defined(__i386__)
- if (IOPMRootDomainGetWillShutdown()) {
- OSKext::freeKCFileSetcontrol();
- }
-#endif // (__x86_64__) || defined(__i386__)
-
#if !NO_KEXTD
OSKextLog(/* kext */ NULL,
kOSKextLogProgressLevel |
kOSKextLogGeneralFlag,
- "System shutdown; requesting immediate " kIOKitDaemonName " exit.");
-
- checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonExit,
- exitRequest);
+ "System shutdown; requesting immediate kextd exit.");
+
+ checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestKextdExit,
+ &exitRequest);
if (checkResult != kOSReturnSuccess) {
goto finish;
}
- if (!sKernelRequests->setObject(exitRequest.get())) {
- goto finish;
- }
-
- OSKext::pingIOKitDaemon();
+ if (!sKernelRequests->setObject(exitRequest)) {
+ goto finish;
+ }
+
+ OSKext::pingKextd();
finish:
#endif
IORecursiveLockUnlock(sKextLock);
+
+ OSSafeReleaseNULL(exitRequest);
return;
-}
-
-void
-OSKext::setWillUserspaceReboot(void)
-{
- OSKext::willShutdown();
- IOService::setWillUserspaceReboot();
- gIOCatalogue->terminateDriversForUserspaceReboot();
-}
-
-void
-OSKext::resetAfterUserspaceReboot(void)
-{
- OSSharedPtr<OSArray> arr = OSArray::withCapacity(1);
- IOService::updateConsoleUsers(arr.get(), 0, true /* after_userspace_reboot */);
-
- IORecursiveLockLock(sKextLock);
- gIOCatalogue->resetAfterUserspaceReboot();
- IOService::userSpaceDidReboot();
- OSKext::removeDaemonExitRequests();
- OSKext::setLoadEnabled(true);
- OSKext::setUnloadEnabled(true);
- OSKext::setAutounloadsEnabled(true);
- OSKext::setKernelRequestsEnabled(true);
- sOSKextWasResetAfterUserspaceReboot = true;
- IORecursiveLockUnlock(sKextLock);
-}
-
-extern "C" int
-OSKextIsInUserspaceReboot(void)
-{
- return IOService::getWillUserspaceReboot();
-}
-
-extern "C" void
-OSKextResetAfterUserspaceReboot(void)
-{
- OSKext::resetAfterUserspaceReboot();
-}
-
-/*
- * Remove daemon exit requests from sKernelRequests
- *
- * If we sent a daemon exit request during a userspace reboot and launchd
- * killed the IOKit daemon before it was able to dequeue the exit request, the
- * next time the daemon starts up it will immediately exit as it gets the old exit request.
- *
- * This removes exit requests so that this does not happen.
- */
-void
-OSKext::removeDaemonExitRequests(void)
-{
- OSDictionary * current = NULL;
- OSString * predicate = NULL;
- size_t index = 0;
- OSSharedPtr<const OSSymbol> predicateKey = OSSymbol::withCString(kKextRequestPredicateKey);
-
- while (index < sKernelRequests->getCount()) {
- current = OSDynamicCast(OSDictionary, sKernelRequests->getObject(index));
- if (current) {
- predicate = OSDynamicCast(OSString, current->getObject(predicateKey.get()));
- if (predicate && predicate->isEqualTo(kKextRequestPredicateRequestDaemonExit)) {
- sKernelRequests->removeObject(index);
- continue;
- }
- }
- index++;
- }
}
/*********************************************************************
@@ -1845,16 +1368,12 @@
bool
OSKext::getAutounloadEnabled(void)
{
-#if XNU_TARGET_OS_OSX
bool result;
IORecursiveLockLock(sKextInnerLock);
result = sAutounloadEnabled ? true : false;
IORecursiveLockUnlock(sKextInnerLock);
return result;
-#else
- return false;
-#endif /* XNU_TARGET_OS_OSX */
}
/*********************************************************************
@@ -1864,7 +1383,6 @@
bool
OSKext::setAutounloadsEnabled(bool flag)
{
-#if XNU_TARGET_OS_OSX
bool result;
IORecursiveLockLock(sKextInnerLock);
@@ -1886,10 +1404,6 @@
IORecursiveLockUnlock(sKextInnerLock);
return result;
-#else
- (void)flag;
- return false;
-#endif /* XNU_TARGET_OS_OSX */
}
/*********************************************************************
@@ -1899,7 +1413,7 @@
OSKext::setAutounloadEnabled(bool flag)
{
bool result = flags.autounloadEnabled ? true : false;
- flags.autounloadEnabled = flag ? (0 == flags.unloadUnsupported) : 0;
+ flags.autounloadEnabled = flag ? 1 : 0;
if (result != (flag ? true : false)) {
OSKextLog(this,
@@ -1949,126 +1463,41 @@
return result;
}
-static bool
-segmentIsMutable(kernel_segment_command_t *seg)
-{
- /* Mutable segments have to have VM_PROT_WRITE */
- if ((seg->maxprot & VM_PROT_WRITE) == 0) {
- return false;
- }
- /* Exclude the __DATA_CONST segment */
- if (strncmp(seg->segname, "__DATA_CONST", sizeof(seg->segname)) == 0) {
- return false;
- }
- /* Exclude __LINKEDIT */
- if (strncmp(seg->segname, "__LINKEDIT", sizeof(seg->segname)) == 0) {
- return false;
- }
- return true;
-}
-
#if PRAGMA_MARK
#pragma mark Kext Life Cycle
#endif
/*********************************************************************
*********************************************************************/
-OSSharedPtr<OSKext>
+OSKext *
OSKext::withPrelinkedInfoDict(
OSDictionary * anInfoDict,
- bool doCoalescedSlides,
- kc_kind_t type)
-{
- OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>());
-
- if (newKext && !newKext->initWithPrelinkedInfoDict(anInfoDict, doCoalescedSlides, type)) {
+ bool doCoalesedSlides)
+{
+ OSKext * newKext = new OSKext;
+
+ if (newKext && !newKext->initWithPrelinkedInfoDict(anInfoDict, doCoalesedSlides)) {
+ newKext->release();
return NULL;
}
return newKext;
}
-OSData *
-OSKext::parseDextUniqueID(
- OSDictionary * anInfoDict,
- const char *dextIDCS)
-{
- OSData *ret = NULL;
- OSData *data_duid = OSDynamicCast(OSData, anInfoDict->getObject(kOSBundleDextUniqueIdentifierKey));
- if (data_duid != NULL) {
- if (data_duid->getLength() > KOSBundleDextUniqueIdentifierMaxLength) {
- OSKextLog(NULL,
- kOSKextLogErrorLevel | kOSKextLogLoadFlag,
- "Dext %s DextUniqueIdentifier too long.",
- dextIDCS);
- } else {
- /*
- * If the DextUniqueID exists it should be
- * present also into the personalities.
- */
- setDextUniqueIDInPersonalities(anInfoDict, data_duid);
- ret = data_duid;
- }
- } else {
- OSKextLog(NULL,
- kOSKextLogDebugLevel | kOSKextLogLoadFlag,
- "Dext %s does not have a DextUniqueIdentifier",
- dextIDCS);
- }
- return ret;
-}
-
-void
-OSKext::setDextUniqueIDInPersonalities(
- OSDictionary * anInfoDict,
- OSData * dextUniqueID)
-{
- OSDictionary * dextPersonalities = NULL;
- OSSharedPtr<OSCollectionIterator> personalitiesIterator;
- OSString * personalityName = NULL;
-
- dextPersonalities = OSDynamicCast(OSDictionary,
- anInfoDict->getObject(kIOKitPersonalitiesKey));
- if (!dextPersonalities || !dextPersonalities->getCount()) {
- return;
- }
-
- personalitiesIterator =
- OSCollectionIterator::withCollection(dextPersonalities);
- if (!personalitiesIterator) {
- return;
- }
- while ((personalityName = OSDynamicCast(OSString,
- personalitiesIterator->getNextObject()))) {
- OSDictionary * personality = OSDynamicCast(OSDictionary,
- dextPersonalities->getObject(personalityName));
- if (personality) {
- OSObject *duid = personality->getObject(kOSBundleDextUniqueIdentifierKey);
- if (duid == NULL) {
- personality->setObject(kOSBundleDextUniqueIdentifierKey, dextUniqueID);
- }
- }
- }
-}
/*********************************************************************
*********************************************************************/
bool
OSKext::initWithPrelinkedInfoDict(
OSDictionary * anInfoDict,
- bool doCoalescedSlides,
- kc_kind_t type)
+ bool doCoalesedSlides)
{
bool result = false;
- OSString * kextPath = NULL; // do not release
- OSNumber * addressNum = NULL; // reused; do not release
- OSNumber * lengthNum = NULL; // reused; do not release
- OSBoolean * scratchBool = NULL; // do not release
- void * data = NULL; // do not free
- void * srcData = NULL; // do not free
- OSSharedPtr<OSData> prelinkedExecutable;
- uint32_t length = 0; // reused
- uintptr_t kext_slide = PE_get_kc_slide(type);
- bool shouldSaveSegments = false;
- kc_format format = KCFormatUnknown;
+ OSString * kextPath = NULL;// do not release
+ OSNumber * addressNum = NULL;// reused; do not release
+ OSNumber * lengthNum = NULL;// reused; do not release
+ void * data = NULL;// do not free
+ void * srcData = NULL;// do not free
+ OSData * prelinkedExecutable = NULL;// must release
+ uint32_t length = 0; // reused
if (!super::init()) {
goto finish;
@@ -2082,35 +1511,35 @@
if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
goto finish;
}
-
#if KASLR_KEXT_DEBUG
- IOLog("kaslr: doCoalescedSlides %d kext %s \n", doCoalescedSlides, getIdentifierCString());
+ IOLog("kaslr: doCoalesedSlides %d kext %s \n", doCoalesedSlides, getIdentifierCString());
#endif
/* Also get the executable's bundle-relative path if present.
* Don't look for an arch-specific path property.
*/
- executableRelPath.reset(OSDynamicCast(OSString,
- anInfoDict->getObject(kPrelinkExecutableRelativePathKey)), OSRetain);
- userExecutableRelPath.reset(OSDynamicCast(OSString,
- anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain);
+ executableRelPath = OSDynamicCast(OSString,
+ anInfoDict->getObject(kPrelinkExecutableRelativePathKey));
+ if (executableRelPath) {
+ executableRelPath->retain();
+ }
+
+ userExecutableRelPath = OSDynamicCast(OSString,
+ anInfoDict->getObject("CFBundleUEXTExecutable"));
+ if (userExecutableRelPath) {
+ userExecutableRelPath->retain();
+ }
/* Don't need the paths to be in the info dictionary any more.
*/
anInfoDict->removeObject(kPrelinkBundlePathKey);
anInfoDict->removeObject(kPrelinkExecutableRelativePathKey);
- scratchBool = OSDynamicCast(OSBoolean,
- getPropertyForHostArch(kOSBundleRequireExplicitLoadKey));
- if (scratchBool == kOSBooleanTrue) {
- flags.requireExplicitLoad = 1;
- }
-
/* Create an OSData wrapper around the linked executable.
*/
addressNum = OSDynamicCast(OSNumber,
anInfoDict->getObject(kPrelinkExecutableLoadKey));
- if (addressNum && addressNum->unsigned64BitValue() != kOSKextCodelessKextLoadAddr) {
+ if (addressNum) {
lengthNum = OSDynamicCast(OSNumber,
anInfoDict->getObject(kPrelinkExecutableSizeKey));
if (!lengthNum) {
@@ -2119,10 +1548,10 @@
kOSKextLogArchiveFlag,
"Kext %s can't find prelinked kext executable size.",
getIdentifierCString());
- return result;
- }
-
- data = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
+ goto finish;
+ }
+
+ data = (void *) ml_static_slide((intptr_t) (addressNum->unsigned64BitValue()));
length = (uint32_t) (lengthNum->unsigned32BitValue());
#if KASLR_KEXT_DEBUG
@@ -2140,7 +1569,7 @@
*/
addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject(kPrelinkExecutableSourceKey));
if (addressNum) {
- srcData = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
+ srcData = (void *) ml_static_slide((intptr_t) (addressNum->unsigned64BitValue()));
#if KASLR_KEXT_DEBUG
IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
@@ -2184,22 +1613,12 @@
goto finish;
}
- /*
- * Fileset KCs are mapped as a whole by iBoot.
- * Individual kext executables should not be unmapped
- * by xnu.
- * Doing so may result in panics like rdar://85419651
- */
- if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) {
- prelinkedExecutable->setDeallocFunction(NULL);
- } else { // Not from a Fileset KC
#if VM_MAPPED_KEXTS
- prelinkedExecutable->setDeallocFunction(osdata_kext_free);
+ prelinkedExecutable->setDeallocFunction(osdata_kext_free);
#else
- prelinkedExecutable->setDeallocFunction(osdata_phys_free);
+ prelinkedExecutable->setDeallocFunction(osdata_phys_free);
#endif
- }
- setLinkedExecutable(prelinkedExecutable.get());
+ setLinkedExecutable(prelinkedExecutable);
addressNum = OSDynamicCast(OSNumber,
anInfoDict->getObject(kPrelinkKmodInfoKey));
if (!addressNum) {
@@ -2212,19 +1631,14 @@
}
if (addressNum->unsigned64BitValue() != 0) {
- kmod_info = (kmod_info_t *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
- if (kmod_info->address) {
- kmod_info->address = (((uintptr_t)(kmod_info->address)) + kext_slide);
- } else {
- kmod_info->address = (uintptr_t)data;
- kmod_info->size = length;
- }
+ kmod_info = (kmod_info_t *) ml_static_slide((intptr_t) (addressNum->unsigned64BitValue()));
+ kmod_info->address = ml_static_slide(kmod_info->address);
#if KASLR_KEXT_DEBUG
IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
- (unsigned long)((vm_offset_t)kmod_info) - kext_slide,
+ (unsigned long)ml_static_unslide((vm_offset_t)kmod_info),
(unsigned long)kmod_info);
IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
- (unsigned long)((vm_offset_t)kmod_info->address) - kext_slide,
+ (unsigned long)ml_static_unslide(kmod_info->address),
(unsigned long)kmod_info->address);
#endif
}
@@ -2251,208 +1665,39 @@
/* If the plist has a UUID for an interface, save that off.
*/
if (isInterface()) {
- interfaceUUID.reset(OSDynamicCast(OSData,
- anInfoDict->getObject(kPrelinkInterfaceUUIDKey)), OSRetain);
+ interfaceUUID = OSDynamicCast(OSData,
+ anInfoDict->getObject(kPrelinkInterfaceUUIDKey));
if (interfaceUUID) {
+ interfaceUUID->retain();
anInfoDict->removeObject(kPrelinkInterfaceUUIDKey);
}
}
- result = (kOSReturnSuccess == slidePrelinkedExecutable(doCoalescedSlides));
- if (!result) {
- goto finish;
- }
-
- kc_type = type;
- /* Exclude builtin and codeless kexts */
- if (prelinkedExecutable && kmod_info) {
- switch (kc_type) {
- case KCKindPrimary:
- shouldSaveSegments = (
- getPropertyForHostArch(kOSMutableSegmentCopy) == kOSBooleanTrue ||
- getPropertyForHostArch(kOSBundleAllowUserLoadKey) == kOSBooleanTrue);
- if (shouldSaveSegments) {
- flags.resetSegmentsFromImmutableCopy = 1;
- } else {
- flags.unloadUnsupported = 1;
- }
- break;
- case KCKindPageable:
- flags.resetSegmentsFromVnode = 1;
- break;
- case KCKindAuxiliary:
- if (!pageableKCloaded) {
- flags.resetSegmentsFromImmutableCopy = 1;
- } else if (resetAuxKCSegmentOnUnload) {
- flags.resetSegmentsFromVnode = 1;
- } else {
- flags.unloadUnsupported = 1;
- }
- break;
- default:
- break;
- }
- }
-
- if (flags.resetSegmentsFromImmutableCopy) {
- /* Save a pristine copy of the mutable segments */
- kernel_segment_command_t *seg = NULL;
- kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address;
-
- savedMutableSegments = OSArray::withCapacity(0);
-
- for (seg = firstsegfromheader(k_mh); seg; seg = nextsegfromheader(k_mh, seg)) {
- if (!segmentIsMutable(seg)) {
- continue;
- }
- uint64_t unslid_vmaddr = seg->vmaddr - kext_slide;
- uint64_t vmsize = seg->vmsize;
- OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag,
- "Saving kext %s mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1);
- OSSharedPtr<OSKextSavedMutableSegment> savedSegment = OSKextSavedMutableSegment::withSegment(seg);
- if (!savedSegment) {
- OSKextLog(this,
- kOSKextLogErrorLevel |
- kOSKextLogGeneralFlag,
- "Kext %s failed to save mutable segment %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
- result = false;
- goto finish;
- }
- savedMutableSegments->setObject(savedSegment);
- }
- }
-
- if (doCoalescedSlides == false && !flags.resetSegmentsFromVnode) {
- /*
- * set VM protections now, wire pages for the old style Aux KC now,
- * wire pages for the rest of the KC types at load time.
- */
- result = (kOSReturnSuccess == setVMAttributes(true, (type == KCKindAuxiliary) ? true : false));
- if (!result) {
+ result = slidePrelinkedExecutable(doCoalesedSlides);
+ if (result != kOSReturnSuccess) {
+ goto finish;
+ }
+
+ if (doCoalesedSlides == false) {
+ /* set VM protections now, wire later at kext load */
+ result = setVMAttributes(true, false);
+ if (result != KERN_SUCCESS) {
goto finish;
}
}
flags.prelinked = true;
-
- if (isDriverKit()) {
- dextStatistics = OSDextStatistics::create();
- dextUniqueID.reset(parseDextUniqueID(anInfoDict, getIdentifierCString()), OSRetain);
- dextLaunchedCount = 0;
- }
/* If we created a kext from prelink info,
* we must be booting from a prelinked kernel.
*/
sPrelinkBoot = true;
- result = (registerIdentifier() == kOSKextInitialized);
+ result = registerIdentifier();
+
finish:
- return result;
-}
-
-/*********************************************************************
-*********************************************************************/
-/* static */
-OSSharedPtr<OSKext>
-OSKext::withCodelessInfo(OSDictionary * anInfoDict, OSKextInitResult *result)
-{
- OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>();
- if (!newKext) {
- return NULL;
- }
-
- OSKextInitResult ret = newKext->initWithCodelessInfo(anInfoDict);
- if (result != NULL) {
- *result = ret;
- }
- if (ret != kOSKextInitialized) {
- return NULL;
- }
-
- return newKext;
-}
-
-/*********************************************************************
-*********************************************************************/
-OSKextInitResult
-OSKext::initWithCodelessInfo(OSDictionary * anInfoDict)
-{
- OSKextInitResult result = kOSKextInitFailure;
- OSString * kextPath = NULL; // do not release
- OSBoolean * scratchBool = NULL; // do not release
-
- if (anInfoDict == NULL || !super::init()) {
- goto finish;
- }
-
- /*
- * Get the path. Don't look for an arch-specific path property.
- */
- kextPath = OSDynamicCast(OSString,
- anInfoDict->getObject(kKextRequestArgumentCodelessInfoBundlePathKey));
- if (!kextPath) {
- OSKextLog(NULL,
- kOSKextLogErrorLevel | kOSKextLogLoadFlag,
- "Requested codeless kext dictionary does not contain the '%s' key",
- kKextRequestArgumentCodelessInfoBundlePathKey);
- goto finish;
- }
-
- uniquePersonalityProperties(anInfoDict);
-
- if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
- goto finish;
- }
-
- /*
- * This path is meant to initialize codeless kexts only. Refuse
- * anything that looks like it has an executable and/or declares
- * itself as a kernel component.
- */
- if (declaresExecutable() || isKernelComponent()) {
- OSKextLog(NULL,
- kOSKextLogErrorLevel | kOSKextLogLoadFlag,
- "Refusing to register codeless kext that declares an executable/kernel component: %s",
- getIdentifierCString());
- goto finish;
- }
-
- if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) {
- boolean_t updated = updateExcludeList(infoDict.get());
- if (updated) {
- OSKextLog(this,
- kOSKextLogDebugLevel | kOSKextLogLoadFlag,
- "KextExcludeList was updated to version: %lld", sExcludeListVersion);
- }
- }
-
- kc_type = KCKindNone;
-
- scratchBool = OSDynamicCast(OSBoolean,
- getPropertyForHostArch(kOSBundleRequireExplicitLoadKey));
- if (scratchBool == kOSBooleanTrue) {
- flags.requireExplicitLoad = 1;
- }
-
- /* Also get the executable's bundle-relative path if present.
- * Don't look for an arch-specific path property.
- */
- userExecutableRelPath.reset(OSDynamicCast(OSString,
- anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain);
-
- /* remove unnecessary paths from the info dict */
- anInfoDict->removeObject(kKextRequestArgumentCodelessInfoBundlePathKey);
-
- if (isDriverKit()) {
- dextStatistics = OSDextStatistics::create();
- dextUniqueID.reset(parseDextUniqueID(anInfoDict, getIdentifierCString()), OSRetain);
- dextLaunchedCount = 0;
- }
-
- result = registerIdentifier();
-
-finish:
+ OSSafeReleaseNULL(prelinkedExecutable);
+
return result;
}
@@ -2462,49 +1707,46 @@
void
OSKext::setAllVMAttributes(void)
{
- OSSharedPtr<OSCollectionIterator> kextIterator;
- const OSSymbol * thisID = NULL; // do not release
+ OSCollectionIterator * kextIterator = NULL;// must release
+ const OSSymbol * thisID = NULL;// do not release
IORecursiveLockLock(sKextLock);
- kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
+ kextIterator = OSCollectionIterator::withCollection(sKextsByID);
if (!kextIterator) {
goto finish;
}
while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
- OSKext * thisKext; // do not release
+ OSKext * thisKext;// do not release
thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
if (!thisKext || thisKext->isInterface() || !thisKext->declaresExecutable()) {
continue;
}
- if (!thisKext->flags.resetSegmentsFromVnode) {
- /*
- * set VM protections now, wire pages for the old style Aux KC now,
- * wire pages for the rest of the KC types at load time.
- */
- thisKext->setVMAttributes(true, (thisKext->kc_type == KCKindAuxiliary) ? true : false);
- }
+ /* set VM protections now, wire later at kext load */
+ thisKext->setVMAttributes(true, false);
}
finish:
IORecursiveLockUnlock(sKextLock);
+ OSSafeReleaseNULL(kextIterator);
return;
}
/*********************************************************************
*********************************************************************/
-OSSharedPtr<OSKext>
+OSKext *
OSKext::withBooterData(
OSString * deviceTreeName,
OSData * booterData)
{
- OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>());
+ OSKext * newKext = new OSKext;
if (newKext && !newKext->initWithBooterData(deviceTreeName, booterData)) {
+ newKext->release();
return NULL;
}
@@ -2528,17 +1770,16 @@
OSData * booterData)
{
bool result = false;
- _BooterKextFileInfo * kextFileInfo = NULL; // do not free
- char * infoDictAddr = NULL; // do not free
- void * executableAddr = NULL; // do not free
- char * bundlePathAddr = NULL; // do not free
-
- OSDictionary * theInfoDict = NULL; // do not release
- OSSharedPtr<OSObject> parsedXML;
- OSSharedPtr<OSString> kextPath;
-
- OSSharedPtr<OSString> errorString;
- OSSharedPtr<OSData> executable;
+ _BooterKextFileInfo * kextFileInfo = NULL;// do not free
+ char * infoDictAddr = NULL;// do not free
+ void * executableAddr = NULL;// do not free
+ char * bundlePathAddr = NULL;// do not free
+
+ OSObject * parsedXML = NULL;// must release
+ OSDictionary * theInfoDict = NULL;// do not release
+ OSString * kextPath = NULL;// must release
+ OSString * errorString = NULL;// must release
+ OSData * executable = NULL;// must release
if (!super::init()) {
goto finish;
@@ -2577,9 +1818,9 @@
goto finish;
}
- parsedXML = OSUnserializeXML(infoDictAddr, errorString);
+ parsedXML = OSUnserializeXML(infoDictAddr, &errorString);
if (parsedXML) {
- theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get());
+ theInfoDict = OSDynamicCast(OSDictionary, parsedXML);
}
if (!theInfoDict) {
const char * errorCString = "(unknown error)";
@@ -2611,7 +1852,7 @@
deviceTreeName->getCStringNoCopy());
goto finish;
}
- bundlePathAddr[kextFileInfo->bundlePathLength - 1] = '\0'; // just in case!
+ bundlePathAddr[kextFileInfo->bundlePathLength - 1] = '\0'; // just in case!
kextPath = OSString::withCString(bundlePathAddr);
if (!kextPath) {
@@ -2624,7 +1865,7 @@
}
}
- if (!setInfoDictionaryAndPath(theInfoDict, kextPath.get())) {
+ if (!setInfoDictionaryAndPath(theInfoDict, kextPath)) {
goto finish;
}
@@ -2657,7 +1898,7 @@
/* A kext with an executable needs to retain the whole booterData
* object to keep the executable in memory.
*/
- if (!setExecutable(executable.get(), booterData)) {
+ if (!setExecutable(executable, booterData)) {
OSKextLog(this,
kOSKextLogErrorLevel |
kOSKextLogGeneralFlag,
@@ -2667,39 +1908,32 @@
}
}
- if (isDriverKit()) {
- dextStatistics = OSDextStatistics::create();
- dextUniqueID.reset(parseDextUniqueID(theInfoDict, getIdentifierCString()), OSRetain);
- dextLaunchedCount = 0;
- }
-
- result = (registerIdentifier() == kOSKextInitialized);
+ result = registerIdentifier();
finish:
+ OSSafeReleaseNULL(parsedXML);
+ OSSafeReleaseNULL(kextPath);
+ OSSafeReleaseNULL(errorString);
+ OSSafeReleaseNULL(executable);
+
return result;
}
/*********************************************************************
*********************************************************************/
-OSKextInitResult
+bool
OSKext::registerIdentifier(void)
{
- OSKextInitResult result = kOSKextInitFailure;
- OSKext * existingKext = NULL; // do not release
- bool existingIsLoaded = false;
- bool existingIsPrelinked = false;
- bool existingIsCodeless = false;
- bool existingIsDext = false;
- OSKextVersion newVersion = -1;
- OSKextVersion existingVersion = -1;
+ bool result = false;
+ OSKext * existingKext = NULL;// do not release
+ bool existingIsLoaded = false;
+ bool existingIsPrelinked = false;
+ OSKextVersion newVersion = -1;
+ OSKextVersion existingVersion = -1;
char newVersionCString[kOSKextVersionMaxLength];
char existingVersionCString[kOSKextVersionMaxLength];
- OSSharedPtr<OSData> newUUID;
- OSSharedPtr<OSData> existingUUID;
- const char *newDextUniqueIDCString = NULL;
- const char *existingDextUniqueIDCString = NULL;
- unsigned int newDextUniqueIDCStringSize = 0;
- unsigned int existingDextUniqueIDCStringSize = 0;
+ OSData * newUUID = NULL;// must release
+ OSData * existingUUID = NULL;// must release
IORecursiveLockLock(sKextLock);
@@ -2712,10 +1946,10 @@
/* If we don't have an existing kext with this identifier,
* just record the new kext and we're done!
*/
- existingKext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID.get()));
+ existingKext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID));
if (!existingKext) {
- sKextsByID->setObject(bundleID.get(), this);
- result = kOSKextInitialized;
+ sKextsByID->setObject(bundleID, this);
+ result = true;
goto finish;
}
@@ -2727,113 +1961,26 @@
existingIsLoaded = existingKext->isLoaded();
existingIsPrelinked = existingKext->isPrelinked();
- existingIsDext = existingKext->isDriverKit();
- existingIsCodeless = !existingKext->declaresExecutable() && !existingIsDext;
-
- /*
- * Check if we are trying to upgrade a dext
- * with another dext.
- */
- if (isDriverKit() && existingIsDext) {
- OSData *newDextUID = getDextUniqueID();
- if (!newDextUID) {
- OSKextLog(this,
- kOSKextLogDebugLevel | kOSKextLogLoadFlag,
- "New dext %s, v%s requested does not have a unique dext identifier\n",
- getIdentifierCString(), newVersionCString);
- goto finish;
- }
- newDextUniqueIDCString = getDextUniqueIDCString(newDextUID, &newDextUniqueIDCStringSize);
- assert(newDextUniqueIDCString != NULL);
-
- OSData *existingDextUID = existingKext->getDextUniqueID();
- if (!existingDextUID) {
- OSKextLog(this,
- kOSKextLogDebugLevel | kOSKextLogLoadFlag,
- "Found a dext %s, v%s: with no unique dext identifier\n",
- existingKext->getIdentifierCString(), existingVersionCString);
- goto finish;
- }
- existingDextUniqueIDCString = getDextUniqueIDCString(existingDextUID, &existingDextUniqueIDCStringSize);
- assert(existingDextUniqueIDCString != NULL);
-
- /*
- * We might get multiple requests to save the same dext.
- * Check if we already have saved it or if this is an upgrade
- * for a dext with the same BundleID.
- * Dexts are uniquely identified by DextUniqueID, if a new DextUniqueID
- * is requested for a BundleID we are going to upgrade to the newest
- * received irrespective from the dext version.
- */
- if (newDextUID->isEqualTo(existingDextUID) && existingKext->flags.dextToReplace == 0) {
- OSKextLog(this,
- kOSKextLogDebugLevel | kOSKextLogLoadFlag,
- "Refusing new dext %s, v%s:"
- "a dext v %s with the same unique dext identifier (%s) already exists\n",
- getIdentifierCString(), newVersionCString,
- existingVersionCString, newDextUniqueIDCString);
- result = kOSKextAlreadyExist;
- goto finish;
- }
-
- bool upgraded = upgradeDext(existingKext, this);
- if (upgraded) {
- /* If the dext was upgraded existingKext might have been deallocated */
- existingKext = NULL;
- OSKextLog(this,
- kOSKextLogDebugLevel | kOSKextLogLoadFlag,
- "Dext %s, v%s , unique dext identifier %s "
- "Upgraded to v%s, unique dext identifier %s \n",
- getIdentifierCString(), existingVersionCString, existingDextUniqueIDCString,
- newVersionCString, newDextUniqueIDCString);
- result = kOSKextInitialized;
- } else {
- OSKextLog(this,
- kOSKextLogDebugLevel | kOSKextLogLoadFlag,
- "Upgrade delayed for %s v%s, unique dext identifier %s "
- "with v%s, unique dext identifier %s.\n",
- getIdentifierCString(), existingVersionCString, existingDextUniqueIDCString,
- newVersionCString, newDextUniqueIDCString);
- result = kOSKextAlreadyExist;
- }
-
- goto finish;
- }
-
- /* If we have a non-codeless kext with this identifier that's already
- * loaded/prelinked, we can't use the new one, but let's be really
- * thorough and check how the two are related for a precise diagnostic
- * log message.
+
+ /* If we have a kext with this identifier that's already loaded/prelinked,
+ * we can't use the new one, but let's be really thorough and check how
+ * the two are related for a precise diagnostic log message.
*
- * This check is valid for kexts that declare an executable and for
- * dexts, but not for codeless kexts - we can just replace those.
- */
- if ((!existingIsCodeless || existingIsDext) &&
- (existingIsLoaded || existingIsPrelinked)) {
+ * Note that user space can't find out about nonloaded prelinked kexts,
+ * so in this case we log a message when new & existing are equivalent
+ * at the step rather than warning level, because we are always going
+ * be getting a copy of the kext in the user load request mkext.
+ */
+ if (existingIsLoaded || existingIsPrelinked) {
bool sameVersion = (newVersion == existingVersion);
- bool sameExecutable = true; // assume true unless we have UUIDs
+ bool sameExecutable = true; // assume true unless we have UUIDs
/* Only get the UUID if the existing kext is loaded. Doing so
* might have to uncompress an mkext executable and we shouldn't
* take that hit when neither kext is loaded.
- *
- * Note: there is no decompression that happens when all kexts
- * are loaded from kext collecitons.
*/
newUUID = copyUUID();
existingUUID = existingKext->copyUUID();
-
- if (existingIsDext && !isDriverKit()) {
- OSKextLog(this,
- kOSKextLogWarningLevel |
- kOSKextLogKextBookkeepingFlag,
- "Notice - new kext %s, v%s matches a %s dext"
- "with the same bundle ID, v%s.",
- getIdentifierCString(), newVersionCString,
- (existingIsLoaded ? "loaded" : "prelinked"),
- existingVersionCString);
- goto finish;
- }
/* I'm entirely too paranoid about checking equivalence of executables,
* but I remember nasty problems with it in the past.
@@ -2842,7 +1989,7 @@
* - If only one kext has a UUID, they're definitely different.
*/
if (newUUID && existingUUID) {
- sameExecutable = newUUID->isEqualTo(existingUUID.get());
+ sameExecutable = newUUID->isEqualTo(existingUUID);
} else if (newUUID || existingUUID) {
sameExecutable = false;
}
@@ -2854,6 +2001,9 @@
* in-kernel for a prelinked kext). We certainly don't want to do
* a whole fake link for the new kext just to compare, either.
*/
+
+ OSKextVersionGetString(version, newVersionCString,
+ sizeof(newVersionCString));
OSKextLog(this,
kOSKextLogWarningLevel |
kOSKextLogKextBookkeepingFlag,
@@ -2896,31 +2046,7 @@
}
}
goto finish;
- } /* if ((!existingIsCodeless || existingIsDext) && (existingIsLoaded || existingIsPrelinked)) */
-
- /* Refuse to allow an existing loaded codeless kext be replaced by a
- * normal kext with the same bundle ID.
- */
- if (existingIsCodeless && declaresExecutable()) {
- OSKextLog(this,
- kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag,
- "Refusing new kext %s, v%s: a codeless copy is already %s",
- getIdentifierCString(), newVersionCString,
- (existingIsLoaded ? "loaded" : "prelinked"));
- goto finish;
- }
-
- /* Dexts packaged in the BootKC will be protected against replacement
- * by non-dexts by the logic above which checks if they are prelinked.
- * Dexts which are prelinked into the System KC will be registered
- * before any other kexts in the AuxKC are registered, and we never
- * put dexts in the AuxKC. Therefore, there is no need to check if an
- * existing object is a dext and is being replaced by a non-dext.
- * The scenario cannot happen by construction.
- *
- * See: OSKext::loadFileSetKexts()
- */
-
+ } /* if (existingIsLoaded || existingIsPrelinked) */
/* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
* user loads are happening or if we're still in early boot. User agents are
@@ -2929,8 +2055,8 @@
* see an older unloaded copy hanging around).
*/
if (sUserLoadsActive) {
- sKextsByID->setObject(bundleID.get(), this);
- result = kOSKextInitialized;
+ sKextsByID->setObject(bundleID, this);
+ result = true;
OSKextLog(this,
kOSKextLogStepLevel |
@@ -2948,8 +2074,8 @@
* kexts might have duplicates.
*/
if (newVersion > existingVersion) {
- sKextsByID->setObject(bundleID.get(), this);
- result = kOSKextInitialized;
+ sKextsByID->setObject(bundleID, this);
+ result = true;
OSKextLog(this,
kOSKextLogStepLevel |
@@ -2975,20 +2101,16 @@
IORecursiveLockUnlock(sKextLock);
- if (newDextUniqueIDCString != NULL) {
- kfree_data(newDextUniqueIDCString, newDextUniqueIDCStringSize);
- }
- if (existingDextUniqueIDCString != NULL) {
- kfree_data(existingDextUniqueIDCString, existingDextUniqueIDCStringSize);
- }
-
- if (result == kOSKextInitialized) {
+ if (result) {
OSKextLog(this,
kOSKextLogStepLevel |
kOSKextLogKextBookkeepingFlag,
"Kext %s, v%s registered and available for loading.",
getIdentifierCString(), newVersionCString);
}
+
+ OSSafeReleaseNULL(newUUID);
+ OSSafeReleaseNULL(existingUUID);
return result;
}
@@ -3003,13 +2125,13 @@
OSString * aPath)
{
bool result = false;
- OSString * bundleIDString = NULL; // do not release
- OSString * versionString = NULL; // do not release
- OSString * compatibleVersionString = NULL; // do not release
- const char * versionCString = NULL; // do not free
- const char * compatibleVersionCString = NULL; // do not free
- OSBoolean * scratchBool = NULL; // do not release
- OSDictionary * scratchDict = NULL; // do not release
+ OSString * bundleIDString = NULL;// do not release
+ OSString * versionString = NULL;// do not release
+ OSString * compatibleVersionString = NULL;// do not release
+ const char * versionCString = NULL;// do not free
+ const char * compatibleVersionCString = NULL;// do not free
+ OSBoolean * scratchBool = NULL;// do not release
+ OSDictionary * scratchDict = NULL;// do not release
if (infoDict) {
panic("Attempt to set info dictionary on a kext "
@@ -3021,7 +2143,8 @@
goto finish;
}
- infoDict.reset(aDictionary, OSRetain);
+ infoDict = aDictionary;
+ infoDict->retain();
/* Check right away if the info dictionary has any log flags.
*/
@@ -3059,7 +2182,8 @@
* just something nice to have for bookkeeping).
*/
if (aPath) {
- path.reset(aPath, OSRetain);
+ path = aPath;
+ path->retain();
}
/*****
@@ -3097,7 +2221,7 @@
goto finish;
}
- compatibleVersion = -1; // set to illegal value for kexts that don't have
+ compatibleVersion = -1; // set to illegal value for kexts that don't have
compatibleVersionString = OSDynamicCast(OSString,
getPropertyForHostArch(kOSBundleCompatibleVersionKey));
@@ -3147,7 +2271,7 @@
getPropertyForHostArch(kOSKernelResourceKey));
if (scratchBool == kOSBooleanTrue) {
flags.kernelComponent = 1;
- flags.interface = 1; // xxx - hm. the kernel itself isn't an interface...
+ flags.interface = 1; // xxx - hm. the kernel itself isn't an interface...
flags.started = 1;
/* A kernel component has one implicit dependency on the kernel.
@@ -3181,7 +2305,7 @@
bool externalDataIsMkext)
{
bool result = false;
- const char * executableKey = NULL; // do not free
+ const char * executableKey = NULL; // do not free
if (!anExecutable) {
infoDict->removeObject(_kOSKextExecutableKey);
@@ -3223,20 +2347,10 @@
static void
uniqueStringPlistProperty(OSDictionary * dict, const char * key)
{
- OSObject * value = NULL; // do not release
- OSString * stringValue = NULL; // do not release
- OSSharedPtr<const OSSymbol> symbolValue;
-
- value = dict->getObject(key);
- if (!value) {
- goto finish;
- }
- if (OSDynamicCast(OSSymbol, value)) {
- /* this is already an OSSymbol: we're good */
- goto finish;
- }
-
- stringValue = OSDynamicCast(OSString, value);
+ OSString * stringValue = NULL;// do not release
+ const OSSymbol * symbolValue = NULL; // must release
+
+ stringValue = OSDynamicCast(OSString, dict->getObject(key));
if (!stringValue) {
goto finish;
}
@@ -3246,9 +2360,13 @@
goto finish;
}
- dict->setObject(key, symbolValue.get());
+ dict->setObject(key, symbolValue);
finish:
+ if (symbolValue) {
+ symbolValue->release();
+ }
+
return;
}
@@ -3257,20 +2375,10 @@
static void
uniqueStringPlistProperty(OSDictionary * dict, const OSString * key)
{
- OSObject * value = NULL; // do not release
- OSString * stringValue = NULL; // do not release
- OSSharedPtr<const OSSymbol> symbolValue;
-
- value = dict->getObject(key);
- if (!value) {
- goto finish;
- }
- if (OSDynamicCast(OSSymbol, value)) {
- /* this is already an OSSymbol: we're good */
- goto finish;
- }
-
- stringValue = OSDynamicCast(OSString, value);
+ OSString * stringValue = NULL;// do not release
+ const OSSymbol * symbolValue = NULL; // must release
+
+ stringValue = OSDynamicCast(OSString, dict->getObject(key));
if (!stringValue) {
goto finish;
}
@@ -3280,34 +2388,32 @@
goto finish;
}
- dict->setObject(key, symbolValue.get());
+ dict->setObject(key, symbolValue);
finish:
+ if (symbolValue) {
+ symbolValue->release();
+ }
+
return;
}
+/*********************************************************************
+* Replace common personality property values with uniqued instances
+* to save on wired memory.
+*********************************************************************/
+/* static */
void
OSKext::uniquePersonalityProperties(OSDictionary * personalityDict)
{
- OSKext::uniquePersonalityProperties(personalityDict, true);
-}
-
-/*********************************************************************
-* Replace common personality property values with uniqued instances
-* to save on wired memory.
-*********************************************************************/
-/* static */
-void
-OSKext::uniquePersonalityProperties(OSDictionary * personalityDict, bool defaultAddKernelBundleIdentifier)
-{
/* Properties every personality has.
*/
uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKey);
uniqueStringPlistProperty(personalityDict, kIOProviderClassKey);
- uniqueStringPlistProperty(personalityDict, gIOClassKey.get());
+ uniqueStringPlistProperty(personalityDict, gIOClassKey);
if (personalityDict->getObject(kCFBundleIdentifierKernelKey)) {
uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKernelKey);
- } else if (defaultAddKernelBundleIdentifier) {
+ } else {
personalityDict->setObject(kCFBundleIdentifierKernelKey, personalityDict->getObject(kCFBundleIdentifierKey));
}
@@ -3343,27 +2449,19 @@
panic("Attempt to free loaded kext %s.", getIdentifierCString());
}
- if (isDriverKit()) {
- if (dextLaunchedCount > 0) {
- panic("Freeing dext %s but dextLaunchedCount is %d\n", getIdentifierCString(), dextLaunchedCount);
- }
- }
-
- infoDict.reset();
- bundleID.reset();
- path.reset();
- executableRelPath.reset();
- userExecutableRelPath.reset();
- dependencies.reset();
- linkedExecutable.reset();
- metaClasses.reset();
- interfaceUUID.reset();
- driverKitUUID.reset();
- dextStatistics.reset();
- dextUniqueID.reset();
+ OSSafeReleaseNULL(infoDict);
+ OSSafeReleaseNULL(bundleID);
+ OSSafeReleaseNULL(path);
+ OSSafeReleaseNULL(executableRelPath);
+ OSSafeReleaseNULL(userExecutableRelPath);
+ OSSafeReleaseNULL(dependencies);
+ OSSafeReleaseNULL(linkedExecutable);
+ OSSafeReleaseNULL(metaClasses);
+ OSSafeReleaseNULL(interfaceUUID);
+ OSSafeReleaseNULL(driverKitUUID);
if (isInterface() && kmod_info) {
- kfree_type(kmod_info_t, kmod_info);
+ kfree(kmod_info, sizeof(kmod_info_t));
}
super::free();
@@ -3373,13 +2471,6 @@
#if PRAGMA_MARK
#pragma mark Mkext files
#endif
-
-#if CONFIG_KXLD
-/*
- * mkext archives are really only relevant on kxld-enabled kernels.
- * Without a dynamic kernel linker, we don't need to support any mkexts.
- */
-
/*********************************************************************
*********************************************************************/
OSReturn
@@ -3388,7 +2479,7 @@
{
OSReturn result = kOSKextReturnBadData;
uint32_t mkextLength = 0;
- mkext_header * mkextHeader = NULL; // do not free
+ mkext_header * mkextHeader = NULL;// do not free
uint32_t mkextVersion = 0;
/* Note default return of kOSKextReturnBadData above.
@@ -3455,30 +2546,22 @@
{
OSReturn result = kOSReturnError;
uint32_t mkextLength;
- mkext2_header * mkextHeader = NULL; // do not free
- void * mkextEnd = NULL; // do not free
+ mkext2_header * mkextHeader = NULL;// do not free
+ void * mkextEnd = NULL;// do not free
uint32_t mkextVersion;
uint8_t * crc_address = NULL;
- size_t crc_buffer_size = 0;
uint32_t checksum;
uint32_t mkextPlistOffset;
uint32_t mkextPlistCompressedSize;
- char * mkextPlistEnd = NULL; // do not free
+ char * mkextPlistEnd = NULL;// do not free
uint32_t mkextPlistFullSize;
- OSSharedPtr<OSString> errorString;
- OSSharedPtr<OSData> mkextPlistUncompressedData;
- const char * mkextPlistDataBuffer = NULL; // do not free
- OSSharedPtr<OSObject> parsedXML;
- OSDictionary * mkextPlist = NULL; // do not release
- OSArray * mkextInfoDictArray = NULL; // do not release
+ OSString * errorString = NULL;// must release
+ OSData * mkextPlistUncompressedData = NULL;// must release
+ const char * mkextPlistDataBuffer = NULL;// do not free
+ OSObject * parsedXML = NULL;// must release
+ OSDictionary * mkextPlist = NULL;// do not release
+ OSArray * mkextInfoDictArray = NULL;// do not release
uint32_t count, i;
- kc_format_t kc_format;
-
- if (!PE_get_primary_kc_format(&kc_format)) {
- OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
- "Unable to determine primary KC format");
- goto finish;
- }
mkextLength = mkextData->getLength();
mkextHeader = (mkext2_header *)mkextData->getBytesNoCopy();
@@ -3486,18 +2569,9 @@
mkextVersion = MKEXT_GET_VERSION(mkextHeader);
crc_address = (u_int8_t *)&mkextHeader->version;
- crc_buffer_size = (uintptr_t)mkextHeader +
- MKEXT_GET_LENGTH(mkextHeader) - (uintptr_t)crc_address;
- if (crc_buffer_size > INT32_MAX) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel |
- kOSKextLogArchiveFlag,
- "Mkext archive size is too large (%lu > INT32_MAX).",
- crc_buffer_size);
- result = kOSKextReturnBadData;
- goto finish;
- }
- checksum = mkext_adler32(crc_address, (int32_t)crc_buffer_size);
+ checksum = mkext_adler32(crc_address,
+ (uintptr_t)mkextHeader +
+ MKEXT_GET_LENGTH(mkextHeader) - (uintptr_t)crc_address);
if (MKEXT_GET_CHECKSUM(mkextHeader) != checksum) {
OSKextLog(/* kext */ NULL,
@@ -3561,9 +2635,9 @@
/* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
*/
- parsedXML = OSUnserializeXML(mkextPlistDataBuffer, errorString);
+ parsedXML = OSUnserializeXML(mkextPlistDataBuffer, &errorString);
if (parsedXML) {
- mkextPlist = OSDynamicCast(OSDictionary, parsedXML.get());
+ mkextPlist = OSDynamicCast(OSDictionary, parsedXML);
}
if (!mkextPlist) {
const char * errorCString = "(unknown error)";
@@ -3578,6 +2652,14 @@
kOSKextLogArchiveFlag,
"Error unserializing mkext plist: %s.", errorCString);
goto finish;
+ }
+
+ /* If the caller needs the plist, hand it back and retain it.
+ * (This function releases it at the end.)
+ */
+ if (mkextPlistOut) {
+ *mkextPlistOut = mkextPlist;
+ (*mkextPlistOut)->retain();
}
mkextInfoDictArray = OSDynamicCast(OSArray,
@@ -3603,30 +2685,9 @@
* Any creation/registration failures are already logged for us.
*/
if (infoDict) {
- OSSharedPtr<OSKext> newKext = OSKext::withMkext2Info(infoDict, mkextData);
-
- /* Fail dynamic loading of a kext when booted from MH_FILESET */
- if (kc_format == KCFormatFileset &&
- newKext &&
- !(newKext->isPrelinked()) &&
- newKext->declaresExecutable()) {
- result = kOSReturnError;
- printf("Kext LOG: Dynamic loading of kext denied for kext %s\n",
- newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext");
-
- OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
- "Dynamic loading of kext denied for kext %s\n",
- newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext");
- goto finish;
- }
- }
- }
-
- /* If the caller needs the plist, hand them back our copy
- */
- if (mkextPlistOut) {
- *mkextPlistOut = mkextPlist;
- parsedXML.detach();
+ OSKext * newKext = OSKext::withMkext2Info(infoDict, mkextData);
+ OSSafeReleaseNULL(newKext);
+ }
}
/* Even if we didn't keep any kexts from the mkext, we may have a load
@@ -3635,38 +2696,26 @@
result = kOSReturnSuccess;
finish:
+
+ OSSafeReleaseNULL(parsedXML);
+ OSSafeReleaseNULL(mkextPlistUncompressedData);
+ OSSafeReleaseNULL(errorString);
+
return result;
}
+/*********************************************************************
+*********************************************************************/
/* static */
-OSReturn
-OSKext::readMkext2Archive(
- OSData * mkextData,
- OSSharedPtr<OSDictionary> &mkextPlistOut,
- uint32_t * checksumPtr)
-{
- OSDictionary * mkextPlist = NULL;
- OSReturn ret;
-
- if (kOSReturnSuccess == (ret = readMkext2Archive(mkextData,
- &mkextPlist,
- checksumPtr))) {
- mkextPlistOut.reset(mkextPlist, OSNoRetain);
- }
- return ret;
-}
-
-/*********************************************************************
-*********************************************************************/
-/* static */
-OSSharedPtr<OSKext>
+OSKext *
OSKext::withMkext2Info(
OSDictionary * anInfoDict,
OSData * mkextData)
{
- OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>();
+ OSKext * newKext = new OSKext;
if (newKext && !newKext->initWithMkext2Info(anInfoDict, mkextData)) {
+ newKext->release();
return NULL;
}
@@ -3681,9 +2730,10 @@
OSData * mkextData)
{
bool result = false;
- OSString * kextPath = NULL; // do not release
- OSNumber * executableOffsetNum = NULL; // do not release
- OSSharedPtr<OSData> executable;
+ OSString * kextPath = NULL;// do not release
+ OSNumber * executableOffsetNum = NULL;// do not release
+ OSCollectionIterator * iterator = NULL;// must release
+ OSData * executable = NULL;// must release
if (anInfoDict == NULL || !super::init()) {
goto finish;
@@ -3700,8 +2750,11 @@
/* If we have a path to the executable, save it.
*/
- executableRelPath.reset(OSDynamicCast(OSString,
- anInfoDict->getObject(kMKEXTExecutableRelativePathKey)), OSRetain);
+ executableRelPath = OSDynamicCast(OSString,
+ anInfoDict->getObject(kMKEXTExecutableRelativePathKey));
+ if (executableRelPath) {
+ executableRelPath->retain();
+ }
/* Don't need the paths to be in the info dictionary any more.
*/
@@ -3717,25 +2770,29 @@
if (!executable) {
goto finish;
}
- if (!setExecutable(executable.get(), mkextData, true)) {
+ if (!setExecutable(executable, mkextData, true)) {
goto finish;
}
}
- result = (registerIdentifier() == kOSKextInitialized);
+ result = registerIdentifier();
+
finish:
+
+ OSSafeReleaseNULL(executable);
+ OSSafeReleaseNULL(iterator);
return result;
}
/*********************************************************************
*********************************************************************/
-OSSharedPtr<OSData>
+OSData *
OSKext::createMkext2FileEntry(
OSData * mkextData,
OSNumber * offsetNum,
const char * name)
{
- OSSharedPtr<OSData> result;
+ OSData * result = NULL;
MkextEntryRef entryRef;
uint8_t * mkextBuffer = (uint8_t *)mkextData->getBytesNoCopy();
uint32_t entryOffset = offsetNum->unsigned32BitValue();
@@ -3747,8 +2804,8 @@
entryRef.mkext = (mkext_basic_header *)mkextBuffer;
entryRef.fileinfo = mkextBuffer + entryOffset;
- if (!result->appendValue(entryRef)) {
- result.reset();
+ if (!result->appendBytes(&entryRef, sizeof(entryRef))) {
+ OSSafeReleaseNULL(result);
goto finish;
}
@@ -3786,20 +2843,19 @@
uint64_t total = ((uint64_t)num_items) * ((uint64_t)size);
//Check for overflow due to multiplication
if (total > UINT32_MAX) {
- panic("z_alloc(%p, %x, %x): overflow caused by %x * %x",
+ panic("z_alloc(%p, %x, %x): overflow caused by %x * %x\n",
notused, num_items, size, num_items, size);
}
uint64_t allocSize64 = total + ((uint64_t)sizeof(zmem));
//Check for overflow due to addition
if (allocSize64 > UINT32_MAX) {
- panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx",
+ panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx\n",
notused, num_items, size, (uint32_t)total, sizeof(zmem));
}
uint32_t allocSize = (uint32_t)allocSize64;
- zmem = (z_mem *)kalloc_data_tag(allocSize, Z_WAITOK,
- VM_KERN_MEMORY_OSKEXT);
+ zmem = (z_mem *)kalloc_tag(allocSize, VM_KERN_MEMORY_OSKEXT);
if (!zmem) {
goto finish;
}
@@ -3814,21 +2870,23 @@
{
uint32_t * skipper = (uint32_t *)ptr - 1;
z_mem * zmem = (z_mem *)skipper;
- kfree_data(zmem, zmem->alloc_size);
+ kfree(zmem, zmem->alloc_size);
+ return;
}
};
-OSSharedPtr<OSData>
+OSData *
OSKext::extractMkext2FileData(
UInt8 * data,
const char * name,
uint32_t compressedSize,
uint32_t fullSize)
{
- OSSharedPtr<OSData> result;
- OSSharedPtr<OSData> uncompressedData; // release on error
-
- uint8_t * uncompressedDataBuffer = NULL; // do not free
+ OSData * result = NULL;
+
+ OSData * uncompressedData = NULL;// release on error
+
+ uint8_t * uncompressedDataBuffer = NULL;// do not free
unsigned long uncompressedSize;
z_stream zstream;
bool zstream_inited = false;
@@ -3845,8 +2903,7 @@
}
if (KERN_SUCCESS != kmem_alloc(kernel_map,
- (vm_offset_t*)&uncompressedDataBuffer, fullSize,
- KMA_DATA_SHARED, VM_KERN_MEMORY_OSKEXT)) {
+ (vm_offset_t*)&uncompressedDataBuffer, fullSize, VM_KERN_MEMORY_OSKEXT)) {
/* How's this for cheesy? The kernel is only asked to extract
* kext plists so we tailor the log messages.
*/
@@ -3972,13 +3029,17 @@
goto finish;
}
- result = os::move(uncompressedData);
+ result = uncompressedData;
finish:
/* Don't bother checking return, nothing we can do on fail.
*/
if (zstream_inited) {
inflateEnd(&zstream);
+ }
+
+ if (!result) {
+ OSSafeReleaseNULL(uncompressedData);
}
return result;
@@ -3998,20 +3059,20 @@
OSReturn result = kOSReturnError;
OSReturn tempResult = kOSReturnError;
- OSSharedPtr<OSData> mkextData;
- OSSharedPtr<OSDictionary> mkextPlist;
-
- OSSharedPtr<OSArray> logInfoArray;
- OSSharedPtr<OSSerialize> serializer;
-
- OSString * predicate = NULL; // do not release
- OSDictionary * requestArgs = NULL; // do not release
-
- OSString * kextIdentifier = NULL; // do not release
- OSNumber * startKextExcludeNum = NULL; // do not release
- OSNumber * startMatchingExcludeNum = NULL; // do not release
- OSBoolean * delayAutounloadBool = NULL; // do not release
- OSArray * personalityNames = NULL; // do not release
+ OSData * mkextData = NULL;// must release
+ OSDictionary * mkextPlist = NULL;// must release
+
+ OSArray * logInfoArray = NULL;// must release
+ OSSerialize * serializer = NULL;// must release
+
+ OSString * predicate = NULL;// do not release
+ OSDictionary * requestArgs = NULL;// do not release
+
+ OSString * kextIdentifier = NULL;// do not release
+ OSNumber * startKextExcludeNum = NULL;// do not release
+ OSNumber * startMatchingExcludeNum = NULL;// do not release
+ OSBoolean * delayAutounloadBool = NULL;// do not release
+ OSArray * personalityNames = NULL;// do not release
/* Default values for these two options: regular autounload behavior,
* load all kexts, send no personalities.
@@ -4072,7 +3133,7 @@
goto finish;
}
- result = readMkext2Archive(mkextData.get(), mkextPlist, NULL);
+ result = readMkext2Archive(mkextData, &mkextPlist, NULL);
if (result != kOSReturnSuccess) {
OSKextLog(/* kext */ NULL,
kOSKextLogErrorLevel |
@@ -4081,7 +3142,7 @@
goto finish;
}
- predicate = _OSKextGetRequestPredicate(mkextPlist.get());
+ predicate = _OSKextGetRequestPredicate(mkextPlist);
if (!predicate || !predicate->isEqualTo(kKextRequestPredicateLoad)) {
OSKextLog(/* kext */ NULL,
kOSKextLogErrorLevel |
@@ -4155,7 +3216,7 @@
if (result != kOSReturnSuccess) {
goto finish;
}
- /* If the load came down from the IOKit daemon, it will shortly inform IOCatalogue
+ /* If the load came down from kextd, it will shortly inform IOCatalogue
* for matching via a separate IOKit calldown.
*/
@@ -4168,7 +3229,7 @@
logInfoArray = OSKext::clearUserSpaceLogFilter();
if (logInfoArray && logInfoOut && logInfoLengthOut) {
- tempResult = OSKext::serializeLogInfo(logInfoArray.get(),
+ tempResult = OSKext::serializeLogInfo(logInfoArray,
logInfoOut, logInfoLengthOut);
if (tempResult != kOSReturnSuccess) {
result = tempResult;
@@ -4176,8 +3237,6 @@
}
OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
-
- IORecursiveLockUnlock(sKextLock);
/* Note: mkextDataObject will have been retained by every kext w/an
* executable in it. That should all have been flushed out at the
@@ -4191,10 +3250,15 @@
"probable memory leak.");
}
+ IORecursiveLockUnlock(sKextLock);
+
+ OSSafeReleaseNULL(mkextData);
+ OSSafeReleaseNULL(mkextPlist);
+ OSSafeReleaseNULL(serializer);
+ OSSafeReleaseNULL(logInfoArray);
+
return result;
}
-
-#endif // CONFIG_KXLD
/*********************************************************************
*********************************************************************/
@@ -4208,8 +3272,8 @@
OSReturn result = kOSReturnError;
char * buffer = NULL;
kern_return_t kmem_result = KERN_FAILURE;
- OSSharedPtr<OSSerialize> serializer;
- char * logInfo = NULL; // returned by reference
+ OSSerialize * serializer = NULL;// must release; reused
+ char * logInfo = NULL;// returned by reference
uint32_t logInfoLength = 0;
if (!logInfoArray || !logInfoOut || !logInfoLengthOut) {
@@ -4230,40 +3294,40 @@
"Failed to create serializer on log info for request from user space.");
/* Incidental error; we're going to (try to) allow the request
* itself to succeed. */
+ }
+
+ if (!logInfoArray->serialize(serializer)) {
+ OSKextLog(/* kext */ NULL,
+ kOSKextLogErrorLevel |
+ kOSKextLogIPCFlag,
+ "Failed to serialize log info for request from user space.");
+ /* Incidental error; we're going to (try to) allow the request
+ * itself to succeed. */
} else {
- if (!logInfoArray->serialize(serializer.get())) {
+ logInfo = serializer->text();
+ logInfoLength = serializer->getLength();
+
+ kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, round_page(logInfoLength), VM_KERN_MEMORY_OSKEXT);
+ if (kmem_result != KERN_SUCCESS) {
OSKextLog(/* kext */ NULL,
kOSKextLogErrorLevel |
kOSKextLogIPCFlag,
- "Failed to serialize log info for request from user space.");
+ "Failed to copy log info for request from user space.");
/* Incidental error; we're going to (try to) allow the request
- * itself to succeed. */
+ * to succeed. */
} else {
- logInfo = serializer->text();
- logInfoLength = serializer->getLength();
-
- kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, round_page(logInfoLength),
- KMA_DATA_SHARED, VM_KERN_MEMORY_OSKEXT);
- if (kmem_result != KERN_SUCCESS) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel |
- kOSKextLogIPCFlag,
- "Failed to copy log info for request from user space.");
- /* Incidental error; we're going to (try to) allow the request
- * to succeed. */
- } else {
- /* 11981737 - clear uninitialized data in last page */
- bzero((void *)(buffer + logInfoLength),
- (round_page(logInfoLength) - logInfoLength));
- memcpy(buffer, logInfo, logInfoLength);
- *logInfoOut = buffer;
- *logInfoLengthOut = logInfoLength;
- }
+ /* 11981737 - clear uninitialized data in last page */
+ bzero((void *)(buffer + logInfoLength),
+ (round_page(logInfoLength) - logInfoLength));
+ memcpy(buffer, logInfo, logInfoLength);
+ *logInfoOut = buffer;
+ *logInfoLengthOut = logInfoLength;
}
}
result = kOSReturnSuccess;
finish:
+ OSSafeReleaseNULL(serializer);
return result;
}
@@ -4272,13 +3336,16 @@
#endif
/*********************************************************************
*********************************************************************/
-OSSharedPtr<OSKext>
+OSKext *
OSKext::lookupKextWithIdentifier(const char * kextIdentifier)
{
- OSSharedPtr<OSKext> foundKext;
+ OSKext * foundKext = NULL;
IORecursiveLockLock(sKextLock);
- foundKext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)), OSRetain);
+ foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
+ if (foundKext) {
+ foundKext->retain();
+ }
IORecursiveLockUnlock(sKextLock);
return foundKext;
@@ -4286,7 +3353,7 @@
/*********************************************************************
*********************************************************************/
-OSSharedPtr<OSKext>
+OSKext *
OSKext::lookupKextWithIdentifier(OSString * kextIdentifier)
{
return OSKext::lookupKextWithIdentifier(kextIdentifier->getCStringNoCopy());
@@ -4294,32 +3361,12 @@
/*********************************************************************
*********************************************************************/
-OSSharedPtr<OSKext>
-OSKext::lookupDextWithIdentifier(OSString * dextIdentifier, OSData *dextUniqueIdentifier)
-{
- OSSharedPtr<OSKext> foundDext;
- foundDext.reset();
-
- IORecursiveLockLock(sKextLock);
- OSKext *dext = OSDynamicCast(OSKext, sKextsByID->getObject(dextIdentifier->getCStringNoCopy()));
- if (dext != NULL && dext->isDriverKit()) {
- if (dext->dextUniqueID == NULL || dext->dextUniqueID->isEqualTo(dextUniqueIdentifier)) {
- foundDext.reset(dext, OSRetain);
- }
- }
- IORecursiveLockUnlock(sKextLock);
-
- return foundDext;
-}
-
-/*********************************************************************
-*********************************************************************/
-OSSharedPtr<OSKext>
+OSKext *
OSKext::lookupKextWithLoadTag(uint32_t aTag)
{
- OSSharedPtr<OSKext> foundKext; // returned
+ OSKext * foundKext = NULL; // returned
uint32_t i, j;
- OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
+ OSArray *list[2] = {sLoadedKexts, sLoadedDriverKitKexts};
uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
IORecursiveLockLock(sKextLock);
@@ -4328,7 +3375,8 @@
for (i = 0; i < count[j]; i++) {
OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
if (thisKext->getLoadTag() == aTag) {
- foundKext.reset(thisKext, OSRetain);
+ foundKext = thisKext;
+ foundKext->retain();
goto finish;
}
}
@@ -4342,79 +3390,40 @@
/*********************************************************************
*********************************************************************/
-OSSharedPtr<OSKext>
+OSKext *
OSKext::lookupKextWithAddress(vm_address_t address)
{
- OSSharedPtr<OSKext> foundKext; // returned
+ OSKext * foundKext = NULL; // returned
uint32_t count, i;
- kmod_info_t *kmod_info;
- vm_address_t originalAddress;
-#if defined(__arm64__)
- uint64_t textExecBase;
- size_t textExecSize;
-#endif /* defined(__arm64__) */
-
- originalAddress = address;
-#if __has_feature(ptrauth_calls)
- address = (vm_address_t)VM_KERNEL_STRIP_PTR(address);
-#endif /* __has_feature(ptrauth_calls) */
IORecursiveLockLock(sKextLock);
count = sLoadedKexts->getCount();
for (i = 0; i < count; i++) {
OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
- if (thisKext == sKernelKext) {
- continue;
- }
- if (thisKext->kmod_info && thisKext->kmod_info->address) {
- kmod_info = thisKext->kmod_info;
- vm_address_t kext_start = kmod_info->address;
- vm_address_t kext_end = kext_start + kmod_info->size;
+ if (thisKext->linkedExecutable) {
+ vm_address_t kext_start =
+ (vm_address_t)thisKext->linkedExecutable->getBytesNoCopy();
+ vm_address_t kext_end = kext_start +
+ thisKext->linkedExecutable->getLength();
if ((kext_start <= address) && (address < kext_end)) {
- foundKext.reset(thisKext, OSRetain);
+ foundKext = thisKext;
+ foundKext->retain();
goto finish;
}
-#if defined(__arm64__)
- textExecBase = (uintptr_t) getsegdatafromheader((kernel_mach_header_t *)kmod_info->address, "__TEXT_EXEC", &textExecSize);
-
- /**
- * If the addresses within the Mach-O are unslid, then manually
- * slide any addresses coming from the Mach-O before usage.
- */
- if (thisKext->flags.unslidMachO) {
- textExecBase = (uintptr_t) ml_static_slide((vm_offset_t) textExecBase);
- }
-
- if ((textExecBase <= address) && (address < textExecBase + textExecSize)) {
- foundKext.reset(thisKext, OSRetain);
- goto finish;
- }
-#endif /* defined (__arm64__) */
- }
- }
-
- if (kernel_text_contains(address)) {
- foundKext.reset(sKernelKext, OSRetain);
- goto finish;
- }
- /*
- * DriverKit userspace executables do not have a kernel linkedExecutable,
- * so we "fake" their address range with the LoadTag. We cannot use the ptrauth-stripped address
- * here, so use the original address passed to this method.
- *
- * This is supposed to be used for logging reasons only. When logd
- * calls this function it ors the address with FIREHOSE_TRACEPOINT_PC_KERNEL_MASK, so we
- * remove it here before checking it against the LoadTag.
- * Also we need to remove FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT set when emitting the log line.
- */
-
- address = originalAddress & ~(FIREHOSE_TRACEPOINT_PC_KERNEL_MASK | FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT);
+ }
+ }
+
count = sLoadedDriverKitKexts->getCount();
for (i = 0; i < count; i++) {
OSKext * thisKext = OSDynamicCast(OSKext, sLoadedDriverKitKexts->getObject(i));
+ /*
+ * DriverKitKexts do not have a linkedExecutable,
+ * so we "fake" their address with the LoadTag
+ */
if (thisKext->getLoadTag() == address) {
- foundKext.reset(thisKext, OSRetain);
+ foundKext = thisKext;
+ foundKext->retain();
}
}
@@ -4424,15 +3433,21 @@
return foundKext;
}
-OSSharedPtr<OSData>
+OSData *
OSKext::copyKextUUIDForAddress(OSNumber *address)
{
- OSSharedPtr<OSData> uuid;
- OSSharedPtr<OSKext> kext;
+ OSData * uuid = NULL;
+ OSKextActiveAccount * active;
+ OSKext * kext = NULL;
+ uint32_t baseIdx;
+ uint32_t lim;
+ uint32_t count, i;
if (!address) {
return NULL;
}
+
+ uintptr_t addr = ml_static_slide((uintptr_t)address->unsigned64BitValue());
#if CONFIG_MACF
/* Is the calling process allowed to query kext info? */
@@ -4454,25 +3469,60 @@
}
#endif
- uintptr_t slidAddress = ml_static_slide((uintptr_t)address->unsigned64BitValue());
- if (slidAddress != 0) {
- kext = lookupKextWithAddress(slidAddress);
- if (kext) {
- uuid = kext->copyTextUUID();
- }
- }
-
- if (!uuid) {
+ IOSimpleLockLock(sKextAccountsLock);
+ // bsearch sKextAccounts list
+ for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
+ active = &sKextAccounts[baseIdx + (lim >> 1)];
+ if ((addr >= active->address) && (addr < active->address_end)) {
+ kext = active->account->kext;
+ if (kext) {
+ kext->retain();
+ }
+ break;
+ } else if (addr > active->address) {
+ // move right
+ baseIdx += (lim >> 1) + 1;
+ lim--;
+ }
+ // else move left
+ }
+ IOSimpleLockUnlock(sKextAccountsLock);
+
+ if (!kext) {
/*
- * If we still don't have a UUID, then we failed to match the slid + stripped address with
- * a kext. This might have happened because the log message came from a dext.
+ * Maybe it is a Dext.
+ * DriverKit userspace executables do not have a kernel linkedExecutable,
+ * so we "fake" their address range with the LoadTag.
*
- * Try again with the original address.
+ * This is supposed to be used for logging reasons only. When logd
+ * calls this function it ors the address with FIREHOSE_TRACEPOINT_PC_KERNEL_MASK, so we
+ * remove it here before checking it against the LoadTag.
+ * Also we need to remove FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT set when emitting the log line.
*/
- kext = lookupKextWithAddress((vm_address_t)address->unsigned64BitValue());
- if (kext && kext->isDriverKit()) {
- uuid = kext->copyTextUUID();
- }
+ addr = (uintptr_t)address->unsigned64BitValue() & ~(FIREHOSE_TRACEPOINT_PC_KERNEL_MASK | FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT);
+ IORecursiveLockLock(sKextLock);
+ count = sLoadedDriverKitKexts->getCount();
+ for (i = 0; i < count; i++) {
+ OSKext * thisKext = NULL;
+
+ thisKext = OSDynamicCast(OSKext, sLoadedDriverKitKexts->getObject(i));
+ if (!thisKext) {
+ continue;
+ }
+ if (thisKext->getLoadTag() == addr) {
+ kext = thisKext;
+ kext->retain();
+ break;
+ }
+ }
+ IORecursiveLockUnlock(sKextLock);
+ }
+
+ if (kext) {
+ uuid = kext->copyTextUUID();
+ kext->release();
+ } else if (((vm_offset_t)addr >= vm_kernel_stext) && ((vm_offset_t)addr < vm_kernel_etext)) {
+ uuid = sKernelKext->copyTextUUID();
}
return uuid;
@@ -4480,12 +3530,12 @@
/*********************************************************************
*********************************************************************/
-OSSharedPtr<OSKext>
+OSKext *
OSKext::lookupKextWithUUID(uuid_t wanted)
{
- OSSharedPtr<OSKext> foundKext; // returned
+ OSKext * foundKext = NULL; // returned
uint32_t j, i;
- OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
+ OSArray *list[2] = {sLoadedKexts, sLoadedDriverKitKexts};
uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
@@ -4500,16 +3550,18 @@
continue;
}
- OSSharedPtr<OSData> uuid_data = thisKext->copyUUID();
+ OSData *uuid_data = thisKext->copyUUID();
if (!uuid_data) {
continue;
}
uuid_t uuid;
memcpy(&uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
+ uuid_data->release();
if (0 == uuid_compare(wanted, uuid)) {
- foundKext.reset(thisKext, OSRetain);
+ foundKext = thisKext;
+ foundKext->retain();
goto finish;
}
}
@@ -4558,18 +3610,17 @@
bool terminateServicesAndRemovePersonalitiesFlag)
{
#if CONFIG_EMBEDDED
- if (!aKext->isDriverKit()) {
- OSKextLog(aKext,
- kOSKextLogErrorLevel |
- kOSKextLogKextBookkeepingFlag,
- "removeKext() called for %s, only supported on embedded for DriverKit dexts",
- aKext->getIdentifier() ? aKext->getIdentifierCString() : "unknown kext");
-
- return kOSReturnSuccess;
- }
-#endif /* CONFIG_EMBEDDED */
+ OSKextLog(aKext,
+ kOSKextLogErrorLevel |
+ kOSKextLogKextBookkeepingFlag,
+ "removeKext() called for %s, not supported on embedded",
+ aKext->getIdentifier() ? aKext->getIdentifierCString() : "unknown kext");
+
+ return kOSReturnSuccess;
+#else /* CONFIG_EMBEDDED */
+
OSReturn result = kOSKextReturnInUse;
- OSKext * checkKext = NULL; // do not release
+ OSKext * checkKext = NULL; // do not release
#if CONFIG_MACF
int macCheckResult = 0;
kauth_cred_t cred = NULL;
@@ -4592,7 +3643,7 @@
goto finish;
}
- if (aKext->isLoaded() || aKext->isDriverKit()) {
+ if (aKext->isLoaded()) {
#if CONFIG_MACF
if (current_task() != kernel_task) {
cred = kauth_cred_get_with_ref();
@@ -4612,16 +3663,7 @@
#endif
/* make sure there are no resource requests in flight - 17187548 */
- if (aKext->declaresExecutable() && aKext->countRequestCallbacks()) {
- goto finish;
- }
- if (aKext->flags.unloadUnsupported) {
- result = kOSKextReturnInUse;
- OSKextLog(aKext,
- kOSKextLogErrorLevel |
- kOSKextLogKextBookkeepingFlag,
- "Can't remove kext %s; unsupported by cache.",
- aKext->getIdentifierCString());
+ if (aKext->countRequestCallbacks()) {
goto finish;
}
@@ -4645,11 +3687,6 @@
result = aKext->unload();
if (result != kOSReturnSuccess) {
- OSKextLog(aKext,
- kOSKextLogErrorLevel |
- kOSKextLogKextBookkeepingFlag,
- "Can't remove kext %s; kext failed to unload - 0x%x.",
- aKext->getIdentifierCString(), result);
goto finish;
}
}
@@ -4664,26 +3701,19 @@
aKext->removePersonalitiesFromCatalog();
}
- if (aKext->isInFileset()) {
- OSKextLog(aKext,
- kOSKextLogProgressLevel |
- kOSKextLogKextBookkeepingFlag,
- "Fileset kext %s unloaded.",
- aKext->getIdentifierCString());
- } else {
- OSKextLog(aKext,
- kOSKextLogProgressLevel |
- kOSKextLogKextBookkeepingFlag,
- "Removing kext %s.",
- aKext->getIdentifierCString());
-
- sKextsByID->removeObject(aKext->getIdentifier());
- }
+ OSKextLog(aKext,
+ kOSKextLogProgressLevel |
+ kOSKextLogKextBookkeepingFlag,
+ "Removing kext %s.",
+ aKext->getIdentifierCString());
+
+ sKextsByID->removeObject(aKext->getIdentifier());
result = kOSReturnSuccess;
finish:
IORecursiveLockUnlock(sKextLock);
return result;
+#endif /* CONFIG_EMBEDDED */
}
/*********************************************************************
@@ -4730,7 +3760,7 @@
OSReturn result = kOSReturnError;
OSKext * foundKext = NULL;
uint32_t i, j;
- OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
+ OSArray *list[2] = {sLoadedKexts, sLoadedDriverKitKexts};
uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
@@ -4767,13 +3797,13 @@
/*********************************************************************
*********************************************************************/
-OSSharedPtr<OSDictionary>
+OSDictionary *
OSKext::copyKexts(void)
{
- OSSharedPtr<OSDictionary> result;
+ OSDictionary * result;
IORecursiveLockLock(sKextLock);
- result = OSDynamicPtrCast<OSDictionary>(sKextsByID->copyCollection());
+ result = OSDynamicCast(OSDictionary, sKextsByID->copyCollection());
IORecursiveLockUnlock(sKextLock);
return result;
@@ -4797,13 +3827,13 @@
OSDictionary * theDictionary,
OSCollectionIterator * theIterator )
{
- OSString * deviceTreeName = NULL; // do not release
- const _DeviceTreeBuffer * deviceTreeBuffer = NULL; // do not release
- char * booterDataPtr = NULL; // do not release
- _BooterKextFileInfo * kextFileInfo = NULL; // do not release
- char * infoDictAddr = NULL; // do not release
- OSSharedPtr<OSObject> parsedXML;
- OSDictionary * theInfoDict = NULL; // do not release
+ OSString * deviceTreeName = NULL;// do not release
+ const _DeviceTreeBuffer * deviceTreeBuffer = NULL;// do not release
+ char * booterDataPtr = NULL;// do not release
+ _BooterKextFileInfo * kextFileInfo = NULL;// do not release
+ char * infoDictAddr = NULL;// do not release
+ OSObject * parsedXML = NULL;// must release
+ OSDictionary * theInfoDict = NULL;// do not release
theIterator->reset();
@@ -4811,8 +3841,10 @@
while ((deviceTreeName =
OSDynamicCast(OSString, theIterator->getNextObject()))) {
const char * devTreeNameCString;
- OSData * deviceTreeEntry; // do not release
- OSString * myBundleID; // do not release
+ OSData * deviceTreeEntry;
+ OSString * myBundleID;// do not release
+
+ OSSafeReleaseNULL(parsedXML);
deviceTreeEntry =
OSDynamicCast(OSData, theDictionary->getObject(deviceTreeName));
@@ -4859,7 +3891,7 @@
continue;
}
- theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get());
+ theInfoDict = OSDynamicCast(OSDictionary, parsedXML);
if (!theInfoDict) {
continue;
}
@@ -4868,16 +3900,17 @@
OSDynamicCast(OSString,
theInfoDict->getObject(kCFBundleIdentifierKey));
if (myBundleID &&
- strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) {
+ strcmp( myBundleID->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0) {
boolean_t updated = updateExcludeList(theInfoDict);
if (!updated) {
/* 25322874 */
- panic("Missing OSKextExcludeList dictionary");
+ panic("Missing OSKextExcludeList dictionary\n");
}
break;
}
- } // while ( (deviceTreeName = ...) )
-
+ } // while ( (deviceTreeName = ...) )
+
+ OSSafeReleaseNULL(parsedXML);
return;
}
@@ -4889,11 +3922,11 @@
void
OSKext::createExcludeListFromPrelinkInfo( OSArray * theInfoArray )
{
- OSDictionary * myInfoDict = NULL; // do not release
- OSString * myBundleID; // do not release
+ OSDictionary * myInfoDict = NULL;// do not release
+ OSString * myBundleID; // do not release
u_int i;
- /* Find the Apple Kext Exclude List. */
+ /* Find com.apple.driver.KextExcludeList. */
for (i = 0; i < theInfoArray->getCount(); i++) {
myInfoDict = OSDynamicCast(OSDictionary, theInfoArray->getObject(i));
if (!myInfoDict) {
@@ -4903,15 +3936,15 @@
OSDynamicCast(OSString,
myInfoDict->getObject(kCFBundleIdentifierKey));
if (myBundleID &&
- strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) {
+ strcmp( myBundleID->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0) {
boolean_t updated = updateExcludeList(myInfoDict);
if (!updated) {
/* 25322874 */
- panic("Missing OSKextExcludeList dictionary");
+ panic("Missing OSKextExcludeList dictionary\n");
}
break;
}
- } // for (i = 0; i < theInfoArray->getCount()...
+ } // for (i = 0; i < theInfoArray->getCount()...
return;
}
@@ -4920,8 +3953,8 @@
boolean_t
OSKext::updateExcludeList(OSDictionary *infoDict)
{
- OSDictionary *myTempDict = NULL; // do not free
- OSString *myTempString = NULL; // do not free
+ OSDictionary *myTempDict = NULL; // do not free
+ OSString *myTempString = NULL;// do not free
OSKextVersion newVersion = 0;
boolean_t updated = false;
@@ -4947,6 +3980,7 @@
IORecursiveLockLock(sKextLock);
if (newVersion > sExcludeListVersion) {
+ OSSafeReleaseNULL(sExcludeListByID);
sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0);
sExcludeListVersion = newVersion;
updated = true;
@@ -4959,21 +3993,12 @@
#if PRAGMA_MARK
#pragma mark Accessors
#endif
-
-/*********************************************************************
-*********************************************************************/
-const OSObject *
-OSKext::getBundleExecutable(void)
-{
- return infoDict->getObject(kCFBundleExecutableKey);
-}
-
/*********************************************************************
*********************************************************************/
const OSSymbol *
OSKext::getIdentifier(void)
{
- return bundleID.get();
+ return bundleID;
}
/*********************************************************************
@@ -5039,19 +4064,18 @@
OSKext::getExecutable(void)
{
OSData * result = NULL;
- OSSharedPtr<OSData> extractedExecutable;
+ OSData * extractedExecutable = NULL; // must release
+ OSData * mkextExecutableRef = NULL;// do not release
if (flags.builtin) {
- return sKernelKext->linkedExecutable.get();
+ return sKernelKext->linkedExecutable;
}
result = OSDynamicCast(OSData, infoDict->getObject(_kOSKextExecutableKey));
if (result) {
- return result;
- }
-
-#if CONFIG_KXLD
- OSData * mkextExecutableRef = NULL; // do not release
+ goto finish;
+ }
+
mkextExecutableRef = OSDynamicCast(OSData,
getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey));
@@ -5082,17 +4106,19 @@
infoDict->removeObject(_kOSKextExecutableExternalDataKey);
if (extractedExecutable && extractedExecutable->getLength()) {
- if (!setExecutable(extractedExecutable.get())) {
+ if (!setExecutable(extractedExecutable)) {
goto finish;
}
- result = extractedExecutable.get();
+ result = extractedExecutable;
} else {
goto finish;
}
}
finish:
-#endif // CONFIG_KXLD
+
+ OSSafeReleaseNULL(extractedExecutable);
+
return result;
}
@@ -5126,20 +4152,6 @@
OSKext::isExecutable(void)
{
return !isKernel() && !isInterface() && declaresExecutable();
-}
-
-/*********************************************************************
-*********************************************************************/
-bool
-OSKext::isSpecialKernelBinary(void)
-{
-#if CONFIG_SPTM
- return (this->kmod_info) &&
- ((this->kmod_info->id == kOSKextSPTMLoadTag) ||
- (this->kmod_info->id == kOSKextTXMLoadTag));
-#else
- return false;
-#endif
}
/*********************************************************************
@@ -5158,14 +4170,9 @@
OSKext::isLoadableInSafeBoot(void)
{
bool result = false;
- OSString * required = NULL; // do not release
+ OSString * required = NULL; // do not release
if (isKernel()) {
- result = true;
- goto finish;
- }
-
- if (isDriverKit()) {
result = true;
goto finish;
}
@@ -5247,7 +4254,7 @@
* from that. Otherwise it's the full load size.
*/
if (kmod_info) {
- *wiredSize = *loadSize - (uint32_t)kmod_info->hdr_size;
+ *wiredSize = *loadSize - kmod_info->hdr_size;
} else {
*wiredSize = *loadSize;
}
@@ -5259,11 +4266,11 @@
/*********************************************************************
*********************************************************************/
-OSSharedPtr<OSData>
+OSData *
OSKext::copyUUID(void)
{
- OSSharedPtr<OSData> result;
- OSData * theExecutable = NULL; // do not release
+ OSData * result = NULL;
+ OSData * theExecutable = NULL;// do not release
const kernel_mach_header_t * header;
/* An interface kext doesn't have a linked executable with an LC_UUID,
@@ -5271,6 +4278,7 @@
*/
if (interfaceUUID) {
result = interfaceUUID;
+ result->retain();
goto finish;
}
@@ -5279,13 +4287,18 @@
}
if (isDriverKit() && infoDict) {
- return driverKitUUID;
+ if (driverKitUUID) {
+ driverKitUUID->retain();
+ return driverKitUUID;
+ } else {
+ return NULL;
+ }
}
/* For real kexts, try to get the UUID from the linked executable,
* or if is hasn't been linked yet, the unrelocated executable.
*/
- theExecutable = linkedExecutable.get();
+ theExecutable = linkedExecutable;
if (!theExecutable) {
theExecutable = getExecutable();
}
@@ -5303,7 +4316,7 @@
/*********************************************************************
*********************************************************************/
-OSSharedPtr<OSData>
+OSData *
OSKext::copyTextUUID(void)
{
if (flags.builtin) {
@@ -5314,10 +4327,10 @@
/*********************************************************************
*********************************************************************/
-OSSharedPtr<OSData>
+OSData *
OSKext::copyMachoUUID(const kernel_mach_header_t * header)
{
- OSSharedPtr<OSData> result;
+ OSData * result = NULL;
const struct load_command * load_cmd = NULL;
const struct uuid_command * uuid_cmd = NULL;
uint32_t i;
@@ -5336,7 +4349,7 @@
for (i = 0; i < header->ncmds; i++) {
if (load_cmd->cmd == LC_UUID) {
uuid_cmd = (struct uuid_command *)load_cmd;
- result = OSData::withValue(uuid_cmd->uuid);
+ result = OSData::withBytes(uuid_cmd->uuid, sizeof(uuid_cmd->uuid));
goto finish;
}
load_cmd = (struct load_command *)((caddr_t)load_cmd + load_cmd->cmdsize);
@@ -5352,424 +4365,6 @@
if (!OSCompareAndSwapPtr(nullptr, uuid, &driverKitUUID)) {
OSSafeReleaseNULL(uuid);
}
-}
-
-OSData *
-OSKext::getDextUniqueID(void)
-{
- if (isDriverKit() && dextUniqueID != NULL) {
- return dextUniqueID.get();
- }
-
- return NULL;
-}
-
-/*
- * In case a DextUniqueID exists this function returns
- * an allocated char* with the hexadecimal represantition of
- * DextUniqueID.
- * The returned pinter needs to be freed with kfree_data, the
- * size of the allocated buffer is returned in size.
- */
-static const char *
-getDextUniqueIDCString(OSData *dextUniqueID, unsigned int *size)
-{
- if (dextUniqueID != NULL) {
- char *s_buffer = NULL;
- unsigned int d_length = dextUniqueID->getLength();
- /*
- * We are converting in hex, so for every byte we will have
- * 2 hex chars and one last \0.
- */
- unsigned int s_length = d_length * 2 + 1;
- s_buffer = (char *) kalloc_data(s_length, Z_WAITOK_ZERO);
-
- char *uid = (char*) dextUniqueID->getBytesNoCopy();
- int cpos = 0;
- for (unsigned int i = 0; i < d_length && cpos < (s_length - 1); i++) {
- int ret = snprintf(s_buffer + cpos, s_length - cpos - 1, "%02X", uid[i]);
- if (ret <= 0) {
- break;
- }
- cpos += ret;
- }
- *size = s_length;
-
- return s_buffer;
- }
-
- return NULL;
-}
-
-/*
- * Atomically swaps the olddext with newdext.
- * olddext will be unloaded, so it might be freed
- * after this call unless it was previously retained.
- *
- * If newdext is NULL, this unloads olddext and does not perform an upgrade
- */
-void
-OSKext::replaceDextInternal(OSKext *olddext, OSKext *newdext)
-{
- OSReturn result;
- const OSSymbol * dextID = olddext->getIdentifier();
- OSData * oldDextUniqueIdentifier = olddext->getDextUniqueID();
- OSSharedPtr<OSArray> new_personalities;
- OSSharedPtr<OSString> kextIdentifier;
- __assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock);
- assert(lock_held);
-
- // The old dext will be unloaded and release dextID, so we need to retain dextID here
- dextID->retain();
-
- if (newdext != NULL) {
- __assert_only bool eq = dextID->isEqualTo(newdext->getIdentifier());
- assert(eq);
- }
-
- if (newdext != NULL) {
- /*
- * Swap the catalog personalities.
- */
- new_personalities = newdext->copyPersonalitiesArray();
- olddext->updatePersonalitiesInCatalog(new_personalities.get());
- }
-
- if (NULL != oldDextUniqueIdentifier) {
- oldDextUniqueIdentifier->retain();
- }
-
- /*
- * Unload the dext.
- */
- result = olddext->unload();
- if (result != kOSReturnSuccess) {
- OSKextLog(NULL,
- kOSKextLogErrorLevel | kOSKextLogLoadFlag,
- "Cannot unload dext for upgrade %s: %d\n",
- dextID->getCStringNoCopy(), result);
- }
-
- if (newdext != NULL) {
- /*
- * Swap the dexts on the OSKext dictionary.
- * This might free the dext.
- */
- sKextsByID->setObject(dextID, newdext);
- } else {
- /*
- * Remove the old dext
- */
- removeKext(olddext, true);
- }
-
- /*
- * Inform userspace.
- */
- if (newdext != NULL) {
- result = notifyDextUpgrade(OSDynamicCast(OSString, dextID), newdext->getDextUniqueID());
- if (result != kOSReturnSuccess) {
- OSKextLog(NULL,
- kOSKextLogErrorLevel | kOSKextLogLoadFlag,
- "Cannot send upgrade notification for %s\n",
- dextID->getCStringNoCopy());
- }
- } else {
- // notify dext removal
- queueKextNotification(kKextRequestPredicateUnloadNotification,
- OSDynamicCast(OSString, dextID), oldDextUniqueIdentifier);
- }
-
- OSSafeReleaseNULL(dextID);
- OSSafeReleaseNULL(oldDextUniqueIdentifier);
-}
-
-/*
- * To be called with sKextLock held.
- * NOTE: this could unload the olddext.
- */
-bool
-OSKext::upgradeDext(OSKext *olddext, OSKext *newdext)
-{
- const char * dextIDCS = newdext->getIdentifierCString();
- __assert_only bool old_isDext = olddext->isDriverKit();
- __assert_only bool new_isDext = newdext->isDriverKit();
- __assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock);
-
- assert(old_isDext && new_isDext);
- assert(lock_held);
-
- /*
- * New dext and old dext have the same ID.
- * We use this ID as key on the OSKext
- * dictionarys/arrays.
- */
- const OSSymbol * dextID = newdext->getIdentifier();
- __assert_only bool eq = dextID->isEqualTo(olddext->getIdentifier());
- assert(eq);
-
- /*
- * Set this OSKect as to update.
- * Note that this flags will never be removed once set.
- * When a OSKext is marked, it will be substitued by a new
- * OSKext, and every subsystem having a reference on this
- * OSKext need to know they have check if they can use
- * this OSKext or look for a new one.
- */
- olddext->flags.dextToReplace = 1;
-
- /*
- * Check if the current OSKext has any
- * userspace processes launched.
- * In this case we cannot upgrade and we have to
- * delay the upgrade until all processes
- * are done.
- */
- if (olddext->dextLaunchedCount == 0) {
- /*
- * Be sure that if there are no launched dexts, no
- * pending upgrades exist.
- * This is an error if it happens, as the decrement
- * should have removed the dext from sDriverKitToUpgradeByID
- * in case it reached 0.
- */
- OSObject *pending_upgdare = sDriverKitToUpgradeByID->getObject(dextID);
- if (pending_upgdare != NULL) {
- OSKextLog(NULL,
- kOSKextLogErrorLevel | kOSKextLogLoadFlag,
- "Pending upgrade found for %s but dextLaunchedCount is 0!\n",
- dextIDCS);
- goto out;
- }
-
- replaceDextInternal(olddext, newdext);
- return true;
- }
-
-out:
-
- /*
- * Delay the upgrade.
- * Make the new dext available in sDriverKitToUpgradeByID.
- * In case there was already a pending upgrade, this will
- * overwrite it.
- */
- sDriverKitToUpgradeByID->setObject(dextID, newdext);
- return false;
-}
-
-/*
- * To be called with sKextLock held.
- * NOTE: this could unload the dext.
- */
-bool
-OSKext::removeDext(OSKext *dext)
-{
- __assert_only bool dext_isDext = dext->isDriverKit();
- __assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock);
- IOReturn result;
-
- assert(dext_isDext);
- assert(lock_held);
-
- /*
- * Set this OSKext to be unloaded when all running instances exit.
- */
- dext->flags.dextToReplace = 1;
-
- result = gIOCatalogue->terminateDriversForModule(
- dext->getIdentifierCString(), /* unload */ false, /* asynchronous */ true);
- if (result != kOSReturnSuccess) {
- OSKextLog(dext,
- kOSKextLogErrorLevel |
- kOSKextLogKextBookkeepingFlag,
- "%s services failed to terminate - 0x%x.",
- dext->getIdentifierCString(), result);
- }
-
- dext->removePersonalitiesFromCatalog();
- sDriverKitToUpgradeByID->removeObject(dext->getIdentifier());
-
- /*
- * Check if the current OSKext has any
- * userspace processes launched.
- * In this case we cannot unload and we have to
- * delay the unload until all processes
- * are done.
- */
- if (dext->dextLaunchedCount == 0) {
- replaceDextInternal(dext, NULL);
- return true;
- }
-
- return false;
-}
-
-bool
-OSKext::incrementDextLaunchCount(OSKext *dext, OSData *dextUniqueIDToMatch)
-{
- bool ret = false;
- __assert_only bool isDext = dext->isDriverKit();
- assert(isDext);
-
- const char * dextIDCS = dext->getIdentifierCString();
- OSData *myDextUniqueID = dext->getDextUniqueID();
-
- if (!myDextUniqueID || !dextUniqueIDToMatch) {
- OSKextLog(dext,
- kOSKextLogErrorLevel | kOSKextLogLoadFlag,
- "Cannot find dext UniqueID for %s, cannot increment dext launches\n",
- dextIDCS);
- return ret;
- }
-
- unsigned int dextUniqueIDCStringSize = 0, dextUniqueIDToMatchCStringSize = 0;
- const char *dextUniqueIDCString = getDextUniqueIDCString(myDextUniqueID, &dextUniqueIDCStringSize);
- const char *dextUniqueIDToMatchCString = getDextUniqueIDCString(dextUniqueIDToMatch, &dextUniqueIDToMatchCStringSize);
- assert(dextUniqueIDCString != NULL);
- assert(dextUniqueIDToMatchCString != NULL);
-
- IORecursiveLockLock(sKextLock);
-
- /*
- * Check that the dext we are referencing is the same
- * looked for the match.
- */
- if (myDextUniqueID->isEqualTo(dextUniqueIDToMatch)) {
- if (dext->flags.dextToReplace == 0 || dext->dextLaunchedCount > 0) {
- if (dext->dextLaunchedCount == kOSKextMaxDextLaunchedCount) {
- OSKextLog(dext,
- kOSKextLogErrorLevel | kOSKextLogLoadFlag,
- "Too many dexts launched for %s UniqueID %s\n",
- dextIDCS, dextUniqueIDCString);
- } else {
- dext->dextLaunchedCount++;
- ret = true;
-
- OSKextLog(dext,
- kOSKextLogProgressLevel | kOSKextLogLoadFlag,
- "New dext launched for %s UniqueID %s",
- dextIDCS, dextUniqueIDCString);
- }
- } else {
- OSKextLog(dext,
- kOSKextLogProgressLevel | kOSKextLogLoadFlag,
- "Dext %s UniqueID %s requires update, cannot launch a new dext\n",
- dextIDCS, dextUniqueIDCString);
- }
- } else {
- OSKextLog(dext,
- kOSKextLogProgressLevel | kOSKextLogLoadFlag,
- "Dext %s: UniqueID %s does not match UniqueID looked for %s, cannot launch a new dext\n",
- dextIDCS, dextUniqueIDCString, dextUniqueIDToMatchCString);
- }
-
- IORecursiveLockUnlock(sKextLock);
-
- if (dextUniqueIDCString != NULL) {
- kfree_data(dextUniqueIDCString, dextUniqueIDCStringSize);
- }
- if (dextUniqueIDToMatchCString != NULL) {
- kfree_data(dextUniqueIDToMatchCString, dextUniqueIDToMatchCStringSize);
- }
- return ret;
-}
-
-bool
-OSKext::decrementDextLaunchCount(OSString *bundleID)
-{
- bool ret = false;
- const char * dextIDCS;
- OSData *myDextUniqueID;
- unsigned int dextUniqueIDCStringSize = 0;
- const char * dextUniqueIDCString = NULL;
- OSKext* dext = NULL;
-
- if (!bundleID) {
- return ret;
- }
- dextIDCS = bundleID->getCStringNoCopy();
-
- IORecursiveLockLock(sKextLock);
-
- /*
- * Look for the dext with the bundle it. This
- * call is triggered only if a previous increment was
- * performed. It means that the dext could have not
- * been upgraded as its dextLaunchedCount was at least 1.
- * Because of this it still needs to be available
- * in sKextsByID.
- */
- dext = OSDynamicCast(OSKext, sKextsByID->getObject(dextIDCS));
- if (!dext || !dext->isDriverKit()) {
- OSKextLog(NULL,
- kOSKextLogErrorLevel | kOSKextLogLoadFlag,
- "Cannot find dext for %s, cannot decrement dext launches\n",
- dextIDCS);
-
- goto out_locked;
- }
-
- myDextUniqueID = dext->getDextUniqueID();
- if (!myDextUniqueID) {
- OSKextLog(dext,
- kOSKextLogErrorLevel | kOSKextLogLoadFlag,
- "Cannot find dext UniqueID for %s, cannot decrement dext launches\n",
- dextIDCS);
-
- goto out_locked;
- }
- dextUniqueIDCString = getDextUniqueIDCString(myDextUniqueID, &dextUniqueIDCStringSize);
- assert(dextUniqueIDCString != NULL);
-
- if (dext->dextLaunchedCount == 0) {
- OSKextLog(dext,
- kOSKextLogErrorLevel | kOSKextLogLoadFlag,
- "Over decrementing dext launch for %s UniqueID %s\n",
- dextIDCS, dextUniqueIDCString);
-
- goto out_locked;
- }
-
- dext->dextLaunchedCount--;
-
- OSKextLog(dext,
- kOSKextLogProgressLevel | kOSKextLogLoadFlag,
- "Dext terminated for %s UniqueID %s",
- dextIDCS, dextUniqueIDCString);
-
- if (dext->dextLaunchedCount == 0 && dext->flags.dextToReplace == 1) {
- /*
- * Find the upgraded dext.
- */
- OSKext *newdext = OSDynamicCast(OSKext, sDriverKitToUpgradeByID->getObject(dextIDCS));
- if (newdext) {
- OSKextLog(dext,
- kOSKextLogProgressLevel | kOSKextLogLoadFlag,
- "Dext upgrade for %s UniqueID %s",
- dextIDCS, dextUniqueIDCString);
- replaceDextInternal(dext, newdext);
- /* NOTE dext could have been freed past this point */
-
- sDriverKitToUpgradeByID->removeObject(dextIDCS);
- } else {
- OSKextLog(dext,
- kOSKextLogProgressLevel | kOSKextLogLoadFlag,
- "Dext unload for %s UniqueID %s",
- dextIDCS, dextUniqueIDCString);
- replaceDextInternal(dext, NULL);
- }
-
- ret = true;
- }
-out_locked:
- IORecursiveLockUnlock(sKextLock);
-
- if (dextUniqueIDCString != NULL) {
- kfree_data(dextUniqueIDCString, dextUniqueIDCStringSize);
- }
-
- return ret;
}
/*********************************************************************
@@ -5805,17 +4400,16 @@
#define ARCH_SEPARATOR_CHAR '_'
static char *
-makeHostArchKey(const char * key, size_t * keySizeOut)
+makeHostArchKey(const char * key, uint32_t * keySizeOut)
{
char * result = NULL;
- size_t keyLength = strlen(key);
- size_t keySize;
+ uint32_t keyLength = strlen(key);
+ uint32_t keySize;
/* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
*/
- keySize = 1 + 1 + keyLength + strlen(ARCHNAME);
- result = (char *)kalloc_data_tag(keySize, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
-
+ keySize = 1 + 1 + strlen(key) + strlen(ARCHNAME);
+ result = (char *)kalloc_tag(keySize, VM_KERN_MEMORY_OSKEXT);
if (!result) {
goto finish;
}
@@ -5835,7 +4429,7 @@
OSKext::getPropertyForHostArch(const char * key)
{
OSObject * result = NULL;// do not release
- size_t hostArchKeySize = 0;
+ uint32_t hostArchKeySize = 0;
char * hostArchKey = NULL;// must kfree
if (!key || !infoDict) {
@@ -5865,7 +4459,7 @@
finish:
if (hostArchKey) {
- kfree_data(hostArchKey, hostArchKeySize);
+ kfree(hostArchKey, hostArchKeySize);
}
return result;
}
@@ -5897,8 +4491,8 @@
bool
OSKext::isInExcludeList(void)
{
- OSString * versionString = NULL; // do not release
- char * versionCString = NULL; // do not free
+ OSString * versionString = NULL;// do not release
+ char * versionCString = NULL;// do not free
size_t i;
boolean_t wantLessThan = false;
boolean_t wantLessThanEqualTo = false;
@@ -5913,7 +4507,7 @@
/* look up by bundleID in our exclude list and if found get version
* string (or strings) that we will not allow to load
*/
- versionString = OSDynamicCast(OSString, sExcludeListByID->getObject(bundleID.get()));
+ versionString = OSDynamicCast(OSString, sExcludeListByID->getObject(bundleID));
if (versionString == NULL || versionString->getLength() > (sizeof(myBuffer) - 1)) {
isInExcludeList = false;
}
@@ -5985,52 +4579,6 @@
}
/*********************************************************************
-* sNonLoadableKextsByID is a dictionary with keys / values of:
-* key = bundleID string of kext we will not allow to load
-* value = boolean (true == loadable, false == not loadable)
-*
-* Only kexts which are in the AuxKC will be marked as "not loadble,"
-* i.e., the value for the kext's bundleID will be false. All kexts in
-* the primary and system KCs will always be marked as "loadable."
-*
-* This list ultimately comes from kexts which have been uninstalled
-* in user space by deleting the kext from disk, but which have not
-* yet been removed from the AuxKC. Because the user could choose to
-* re-install the exact same version of the kext, we need to keep
-* a dictionary of boolean values so that user space only needs to
-* keep a simple list of "uninstalled" or "missing" bundles. When
-* a bundle is re-installed, the iokit daemon can use the
-* AucKCBundleAvailable predicate to set the individual kext's
-* availability to true.
-*********************************************************************/
-bool
-OSKext::isLoadable(void)
-{
- bool isLoadable = true;
-
- if (kc_type != KCKindAuxiliary) {
- /* this filtering only applies to kexts in the auxkc */
- return true;
- }
-
- IORecursiveLockLock(sKextLock);
-
- if (sNonLoadableKextsByID) {
- /* look up by bundleID in our exclude list and if found get version
- * string (or strings) that we will not allow to load
- */
- OSBoolean *loadableVal;
- loadableVal = OSDynamicCast(OSBoolean, sNonLoadableKextsByID->getObject(bundleID.get()));
- if (loadableVal && !loadableVal->getValue()) {
- isLoadable = false;
- }
- }
- IORecursiveLockUnlock(sKextLock);
-
- return isLoadable;
-}
-
-/*********************************************************************
*********************************************************************/
/* static */
OSReturn
@@ -6043,45 +4591,20 @@
OSArray * personalityNames)
{
OSReturn result = kOSReturnError;
- OSSharedPtr<OSString> kextIdentifier;
+ OSString * kextIdentifier = NULL; // must release
kextIdentifier = OSString::withCString(kextIdentifierCString);
if (!kextIdentifier) {
result = kOSKextReturnNoMemory;
goto finish;
}
- result = OSKext::loadKextWithIdentifier(kextIdentifier.get(),
+ result = OSKext::loadKextWithIdentifier(kextIdentifier,
NULL /* kextRef */,
allowDeferFlag, delayAutounloadFlag,
startOpt, startMatchingOpt, personalityNames);
finish:
- return result;
-}
-
-OSReturn
-OSKext::loadKextWithIdentifier(
- OSString * kextIdentifier,
- OSSharedPtr<OSObject> &kextRef,
- Boolean allowDeferFlag,
- Boolean delayAutounloadFlag,
- OSKextExcludeLevel startOpt,
- OSKextExcludeLevel startMatchingOpt,
- OSArray * personalityNames)
-{
- OSObject * kextRefRaw = NULL;
- OSReturn result;
-
- result = loadKextWithIdentifier(kextIdentifier,
- &kextRefRaw,
- allowDeferFlag,
- delayAutounloadFlag,
- startOpt,
- startMatchingOpt,
- personalityNames);
- if ((kOSReturnSuccess == result) && kextRefRaw) {
- kextRef.reset(kextRefRaw, OSNoRetain);
- }
+ OSSafeReleaseNULL(kextIdentifier);
return result;
}
@@ -6099,9 +4622,9 @@
{
OSReturn result = kOSReturnError;
OSReturn pingResult = kOSReturnError;
- OSKext * theKext = NULL; // do not release
- OSSharedPtr<OSDictionary> loadRequest;
- OSSharedPtr<const OSSymbol> kextIdentifierSymbol;
+ OSKext * theKext = NULL;// do not release
+ OSDictionary * loadRequest = NULL;// must release
+ const OSSymbol * kextIdentifierSymbol = NULL;// must release
if (kextRef) {
*kextRef = NULL;
@@ -6141,23 +4664,23 @@
* in sKernelRequests for this bundle identifier
*/
kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
- if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) {
+ if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol)) {
result = _OSKextCreateRequest(kKextRequestPredicateRequestLoad,
- loadRequest);
+ &loadRequest);
if (result != kOSReturnSuccess) {
goto finish;
}
- if (!_OSKextSetRequestArgument(loadRequest.get(),
+ if (!_OSKextSetRequestArgument(loadRequest,
kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
result = kOSKextReturnNoMemory;
goto finish;
}
- if (!sKernelRequests->setObject(loadRequest.get())) {
+ if (!sKernelRequests->setObject(loadRequest)) {
result = kOSKextReturnNoMemory;
goto finish;
}
- if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) {
+ if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol)) {
result = kOSKextReturnNoMemory;
goto finish;
}
@@ -6169,12 +4692,12 @@
kextIdentifier->getCStringNoCopy());
}
- pingResult = OSKext::pingIOKitDaemon();
+ pingResult = OSKext::pingKextd();
if (pingResult == kOSKextReturnDisabled) {
OSKextLog(/* kext */ NULL,
((sPrelinkBoot) ? kOSKextLogDebugLevel : kOSKextLogErrorLevel) |
kOSKextLogLoadFlag,
- "Kext %s might not load - " kIOKitDaemonName " is currently unavailable.",
+ "Kext %s might not load - kextd is currently unavailable.",
kextIdentifier->getCStringNoCopy());
}
@@ -6191,10 +4714,8 @@
"Failed to load kext %s (error 0x%x).",
kextIdentifier->getCStringNoCopy(), (int)result);
- if (theKext->kc_type == KCKindUnknown) {
- OSKext::removeKext(theKext,
- /* terminateService/removePersonalities */ true);
- }
+ OSKext::removeKext(theKext,
+ /* terminateService/removePersonalities */ true);
goto finish;
}
@@ -6208,207 +4729,19 @@
}
finish:
+ OSSafeReleaseNULL(loadRequest);
+ OSSafeReleaseNULL(kextIdentifierSymbol);
+
if ((kOSReturnSuccess == result) && kextRef) {
+ theKext->retain();
+ theKext->matchingRefCount++;
*kextRef = theKext;
- theKext->matchingRefCount++;
- theKext->retain();
}
IORecursiveLockUnlock(sKextLock);
return result;
}
-
-/*********************************************************************
-*********************************************************************/
-/* static */
-OSReturn
-OSKext::loadKextFromKC(OSKext *theKext, OSDictionary *requestDict)
-{
- OSReturn result = kOSReturnError;
-
- OSBoolean *delayAutounloadBool = NULL; // do not release
- OSNumber *startKextExcludeNum = NULL; // do not release
- OSNumber *startMatchingExcludeNum = NULL; // do not release
- OSArray *personalityNames = NULL; // do not release
-
- /*
- * Default values for these options:
- * regular autounload behavior
- * start the kext
- * send all personalities to the catalog
- */
- Boolean delayAutounload = false;
- OSKextExcludeLevel startKextExcludeLevel = kOSKextExcludeNone;
- OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeNone;
-
- IORecursiveLockLock(sKextLock);
-
- OSKextLog(/* kext */ NULL,
- kOSKextLogDebugLevel |
- kOSKextLogIPCFlag,
- "Received kext KC load request from user space.");
-
- /* Regardless of processing, the fact that we have gotten here means some
- * user-space program is up and talking to us, so we'll switch our kext
- * registration to reflect that.
- */
- if (!sUserLoadsActive) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogProgressLevel |
- kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
- "Switching to late startup (user-space) kext loading policy.");
- sUserLoadsActive = true;
- }
-
- delayAutounloadBool = OSDynamicCast(OSBoolean,
- _OSKextGetRequestArgument(requestDict,
- kKextRequestArgumentDelayAutounloadKey));
- startKextExcludeNum = OSDynamicCast(OSNumber,
- _OSKextGetRequestArgument(requestDict,
- kKextRequestArgumentStartExcludeKey));
- startMatchingExcludeNum = OSDynamicCast(OSNumber,
- _OSKextGetRequestArgument(requestDict,
- kKextRequestArgumentStartMatchingExcludeKey));
- personalityNames = OSDynamicCast(OSArray,
- _OSKextGetRequestArgument(requestDict,
- kKextRequestArgumentPersonalityNamesKey));
-
- if (delayAutounloadBool) {
- delayAutounload = delayAutounloadBool->getValue();
- }
- if (startKextExcludeNum) {
- startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
- }
- if (startMatchingExcludeNum) {
- startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
- }
-
- OSKextLog(/* kext */ NULL,
- kOSKextLogProgressLevel |
- kOSKextLogIPCFlag,
- "Received request from user space to load KC kext %s.",
- theKext->getIdentifierCString());
-
- /* this could be in the Auxiliary KC, so record the load request */
- OSKext::recordIdentifierRequest(OSDynamicCast(OSString, theKext->getIdentifier()));
-
- /*
- * Load the kext
- */
- result = theKext->load(startKextExcludeLevel,
- startMatchingExcludeLevel, personalityNames);
-
- if (result != kOSReturnSuccess) {
- OSKextLog(theKext,
- kOSKextLogErrorLevel |
- kOSKextLogLoadFlag,
- "Failed to load kext %s (error 0x%x).",
- theKext->getIdentifierCString(), (int)result);
-
- OSKext::removeKext(theKext,
- /* terminateService/removePersonalities */ true);
- goto finish;
- } else {
- OSKextLog(theKext,
- kOSKextLogProgressLevel |
- kOSKextLogLoadFlag,
- "Kext %s Loaded successfully from %s KC",
- theKext->getIdentifierCString(), theKext->getKCTypeString());
- }
-
- if (delayAutounload) {
- OSKextLog(theKext,
- kOSKextLogProgressLevel |
- kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
- "Setting delayed autounload for %s.",
- theKext->getIdentifierCString());
- theKext->flags.delayAutounload = 1;
- }
-
-finish:
- IORecursiveLockUnlock(sKextLock);
-
- return result;
-}
-
-/*********************************************************************
-*********************************************************************/
-/* static */
-OSReturn
-OSKext::loadCodelessKext(OSString *kextIdentifier, OSDictionary *requestDict)
-{
- OSReturn result = kOSReturnError;
- OSDictionary *anInfoDict = NULL; // do not release
-
- anInfoDict = OSDynamicCast(OSDictionary,
- _OSKextGetRequestArgument(requestDict,
- kKextRequestArgumentCodelessInfoKey));
- if (anInfoDict == NULL) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel |
- kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
- "Missing 'Codeless Kext Info' dictionary in codeless kext load request of %s.",
- kextIdentifier->getCStringNoCopy());
- return kOSKextReturnInvalidArgument;
- }
-
- IORecursiveLockLock(sKextLock);
-
- OSKextLog(/* kext */ NULL,
- kOSKextLogProgressLevel |
- kOSKextLogIPCFlag,
- "Received request from user space to load codeless kext %s.",
- kextIdentifier->getCStringNoCopy());
-
- {
- // instantiate a new kext, and don't hold a reference
- // (the kext subsystem will hold one implicitly)
- OSKextInitResult ret;
- OSSharedPtr<OSKext> newKext = OSKext::withCodelessInfo(anInfoDict, &ret);
- if (!newKext) {
- /*
- * We might have failed to create a new OSKext
- * because the old one should still be used.
- * Check if that is the case.
- */
- if (ret != kOSKextInitFailure) {
- result = kOSReturnSuccess;
- goto finish;
- }
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel |
- kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
- "Could not instantiate codeless kext.");
- result = kOSKextReturnNotLoadable;
- goto finish;
- }
- if (!kextIdentifier->isEqualTo(newKext->getIdentifierCString())) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel |
- kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
- "Codeless kext identifiers don't match '%s' != '%s'",
- kextIdentifier->getCStringNoCopy(), newKext->getIdentifierCString());
-
- OSKext::removeKext(newKext.get(), false);
- result = kOSKextReturnInvalidArgument;
- goto finish;
- }
-
- /* Record the request for the codeless kext */
- OSKext::recordIdentifierRequest(OSDynamicCast(OSString, newKext->getIdentifier()));
-
- result = kOSReturnSuccess;
- /* Send the kext's personalities to the IOCatalog. This is an explicit load. */
- result = newKext->sendPersonalitiesToCatalog(true, NULL);
- }
-
-finish:
- IORecursiveLockUnlock(sKextLock);
-
- return result;
-}
-
/*********************************************************************
*********************************************************************/
/* static */
@@ -6435,7 +4768,7 @@
OSKext::recordIdentifierRequest(
OSString * kextIdentifier)
{
- OSSharedPtr<const OSSymbol> kextIdentifierSymbol;
+ const OSSymbol * kextIdentifierSymbol = NULL; // must release
bool fail = false;
if (!sAllKextLoadIdentifiers || !kextIdentifier) {
@@ -6450,8 +4783,8 @@
}
IORecursiveLockLock(sKextLock);
- if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) {
- if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) {
+ if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol)) {
+ if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol)) {
fail = true;
} else {
// xxx - need to find a way to associate this whole func w/the kext
@@ -6474,6 +4807,7 @@
"Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
kextIdentifier->getCStringNoCopy());
}
+ OSSafeReleaseNULL(kextIdentifierSymbol);
return;
}
@@ -6486,11 +4820,12 @@
OSArray * personalityNames)
{
OSReturn result = kOSReturnError;
+ kern_return_t kxldResult;
OSKextExcludeLevel dependenciesStartOpt = startOpt;
OSKextExcludeLevel dependenciesStartMatchingOpt = startMatchingOpt;
unsigned int i, count;
Boolean alreadyLoaded = false;
- OSKext * lastLoadedKext = NULL; // do not release
+ OSKext * lastLoadedKext = NULL;
if (isInExcludeList()) {
OSKextLog(this,
@@ -6502,16 +4837,6 @@
result = kOSKextReturnNotLoadable;
goto finish;
}
- if (!isLoadable()) {
- OSKextLog(this,
- kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
- kOSKextLogLoadFlag,
- "Kext %s is not loadable",
- getIdentifierCString());
-
- result = kOSKextReturnNotLoadable;
- goto finish;
- }
if (isLoaded()) {
alreadyLoaded = true;
@@ -6526,26 +4851,7 @@
}
#if CONFIG_MACF
- /*
- * On kxld and on embedded, only call into the MAC hook when on a
- * user thread, for access control over userspace kextloads.
- *
- * On non-kxld systems, additionally check the MAC hook for kexts in
- * the Pageable and Aux KCs, regardless of whether we are on a user
- * thread or not. This means on Apple silicon devices that the MAC
- * hook will only be useful to block 3rd party kexts loaded via
- * matching, and any kexts loaded from userspace kextloads.
- *
- * Note that this should _not_ be called on kexts loaded from the
- * kernel bootstrap thread as the kernel proc's cred struct is not
- * yet initialized! This won't happen on macOS because all the kexts
- * in the BootKC are self-contained and their kc_type = KCKindPrimary.
- */
- if (current_task() != kernel_task
-#if XNU_TARGET_OS_OSX && !CONFIG_KXLD
- || (kc_type != KCKindPrimary && kc_type != KCKindUnknown)
-#endif
- ) {
+ if (current_task() != kernel_task) {
int macCheckResult = 0;
kauth_cred_t cred = NULL;
@@ -6562,7 +4868,7 @@
goto finish;
}
}
-#endif /* CONFIG_MACF */
+#endif
if (!sLoadEnabled) {
OSKextLog(this,
@@ -6595,8 +4901,8 @@
* AppleKextExcludeList. Detect that special kext by bundle identifier and
* load its metadata into the global data structures, if appropriate
*/
- if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) {
- boolean_t updated = updateExcludeList(infoDict.get());
+ if (strcmp(getIdentifierCString(), "com.apple.driver.KextExcludeList") == 0) {
+ boolean_t updated = updateExcludeList(infoDict);
if (updated) {
OSKextLog(this,
kOSKextLogDebugLevel | kOSKextLogLoadFlag,
@@ -6631,21 +4937,7 @@
"Loading kext %s.",
getIdentifierCString());
-#if !VM_MAPPED_KEXTS
- if (isPrelinked() == false) {
- OSKextLog(this,
- kOSKextLogErrorLevel |
- kOSKextLogLoadFlag,
- "Can't load kext %s - not in a kext collection.",
- getIdentifierCString());
- result = kOSKextReturnDisabled;
- goto finish;
- }
-#endif /* defined(__x86_64__) */
-
-#if CONFIG_KXLD
if (!sKxldContext) {
- kern_return_t kxldResult;
kxldResult = kxld_create_context(&sKxldContext, &kern_allocate,
&kxld_log_callback, /* Flags */ (KXLDFlags) 0,
/* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0);
@@ -6659,7 +4951,6 @@
goto finish;
}
}
-#endif // CONFIG_KXLD
/* We only need to resolve dependencies once for the whole graph, but
* resolveDependencies will just return if there's no work to do, so it's
@@ -6737,22 +5028,15 @@
// The kernel PRNG is not initialized when the first kext is
// loaded, so use early random
uuid_generate_early_random(instance_uuid);
- account = IOMallocType(OSKextAccount);
-
+ account = IONew(OSKextAccount, 1);
+ if (!account) {
+ result = KERN_MEMORY_ERROR;
+ goto finish;
+ }
+ bzero(account, sizeof(*account));
account->loadTag = kmod_info->id;
account->site.refcount = 0;
account->site.flags = VM_TAG_KMOD;
-
-#if DEVELOPMENT || DEBUG
- /* Setup the task reference group. */
- (void)snprintf(account->task_refgrp_name, sizeof(account->task_refgrp_name),
- "task_%s", getIdentifierCString());
- account->task_refgrp.grp_name = account->task_refgrp_name;
- account->task_refgrp.grp_parent = &task_external_refgrp;
- account->task_refgrp.grp_flags = OS_REFGRP_F_ALWAYS_ENABLED;
- os_ref_log_init(&account->task_refgrp);
-#endif /* DEVELOPMENT || DEBUG */
-
account->kext = this;
if (gIOSurfaceIdentifier == bundleID) {
vm_tag_alloc(&account->site);
@@ -6853,12 +5137,11 @@
getIdentifierCString());
queueKextNotification(kKextRequestPredicateLoadNotification,
- OSDynamicCast(OSString, bundleID.get()), getDextUniqueID());
+ OSDynamicCast(OSString, bundleID));
}
return result;
}
-#if CONFIG_KXLD
/*********************************************************************
*
*********************************************************************/
@@ -6873,7 +5156,7 @@
}
size = 1 + strlen(string);
- result = (char *)kalloc_data_tag(size, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
+ result = (char *)kalloc_tag(size, VM_KERN_MEMORY_OSKEXT);
if (!result) {
goto finish;
}
@@ -6883,7 +5166,6 @@
finish:
return result;
}
-#endif // CONFIG_KXLD
/*********************************************************************
*
@@ -6925,7 +5207,7 @@
*********************************************************************/
OSReturn
-OSKext::slidePrelinkedExecutable(bool doCoalescedSlides)
+OSKext::slidePrelinkedExecutable(bool doCoalesedSlides)
{
OSReturn result = kOSKextReturnBadData;
kernel_mach_header_t * mh = NULL;
@@ -6944,7 +5226,6 @@
uint32_t i = 0;
int reloc_size;
vm_offset_t new_kextsize;
- kc_format format = KCFormatUnknown;
if (linkedExecutable == NULL || flags.builtin) {
result = kOSReturnSuccess;
@@ -6952,12 +5233,6 @@
}
mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
- if (kernel_mach_header_is_in_fileset(mh)) {
- // kexts in filesets are slid as part of collection sliding
- result = kOSReturnSuccess;
- goto finish;
- }
-
segmentSplitInfo = (struct linkedit_data_command *) getcommandfromheader(mh, LC_SEGMENT_SPLIT_INFO);
for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
@@ -6999,7 +5274,7 @@
symtab = (struct symtab_command *) getcommandfromheader(mh, LC_SYMTAB);
- if (symtab != NULL && doCoalescedSlides == false) {
+ if (symtab != NULL && doCoalesedSlides == false) {
/* Some pseudo-kexts have symbol tables without segments.
* Ignore them. */
if (symtab->nsyms > 0 && haveLinkeditBase) {
@@ -7022,7 +5297,7 @@
}
}
- if (dysymtab != NULL && doCoalescedSlides == false) {
+ if (dysymtab != NULL && doCoalesedSlides == false) {
if (dysymtab->nextrel > 0) {
OSKextLog(this,
kOSKextLogErrorLevel | kOSKextLogLoadFlag |
@@ -7092,20 +5367,12 @@
* For now, we do not free LINKEDIT for kexts with split segments.
*/
new_kextsize = round_page(kmod_info->size - reloc_size);
- if (new_kextsize > UINT_MAX) {
- OSKextLog(this,
- kOSKextLogErrorLevel | kOSKextLogLoadFlag |
- kOSKextLogLinkFlag,
- "Kext %s: new kext size is too large.",
- getIdentifierCString());
- goto finish;
- }
if (((kmod_info->size - new_kextsize) > PAGE_SIZE) && (!segmentSplitInfo)) {
vm_offset_t endofkext = kmod_info->address + kmod_info->size;
vm_offset_t new_endofkext = kmod_info->address + new_kextsize;
vm_offset_t endofrelocInfo = (vm_offset_t) (((uint8_t *)reloc) + reloc_size);
- size_t bytes_remaining = endofkext - endofrelocInfo;
- OSSharedPtr<OSData> new_osdata;
+ int bytes_remaining = endofkext - endofrelocInfo;
+ OSData * new_osdata = NULL;
/* fix up symbol offsets if they are after the dsymtab local relocs */
if (symtab) {
@@ -7131,28 +5398,19 @@
linkeditSeg->vmsize = round_page(linkeditSeg->vmsize - reloc_size);
linkeditSeg->filesize = linkeditSeg->vmsize;
- new_osdata = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)new_kextsize);
+ new_osdata = OSData::withBytesNoCopy((void *)kmod_info->address, new_kextsize);
if (new_osdata) {
/* Fix up kmod info and linkedExecutable.
*/
kmod_info->size = new_kextsize;
- /*
- * Fileset KCs are mapped as a whole by iBoot.
- * Individual kext executables should not be unmapped
- * by xnu.
- * Doing so may result in panics like rdar://85419651
- */
- if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) {
- new_osdata->setDeallocFunction(NULL);
- } else { // Not from a Fileset KC
#if VM_MAPPED_KEXTS
- new_osdata->setDeallocFunction(osdata_kext_free);
+ new_osdata->setDeallocFunction(osdata_kext_free);
#else
- new_osdata->setDeallocFunction(osdata_phys_free);
+ new_osdata->setDeallocFunction(osdata_phys_free);
#endif
- }
linkedExecutable->setDeallocFunction(NULL);
- linkedExecutable = os::move(new_osdata);
+ linkedExecutable->release();
+ linkedExecutable = new_osdata;
#if VM_MAPPED_KEXTS
kext_free(new_endofkext, (endofkext - new_endofkext));
@@ -7178,22 +5436,19 @@
OSKext::loadExecutable()
{
OSReturn result = kOSReturnError;
- OSSharedPtr<OSArray> linkDependencies;
+ kern_return_t kxldResult;
+ KXLDDependency * kxlddeps = NULL;// must kfree
+ uint32_t num_kxlddeps = 0;
+ OSArray * linkDependencies = NULL;// must release
+ uint32_t numDirectDependencies = 0;
uint32_t num_kmod_refs = 0;
- OSData * theExecutable = NULL; // do not release
- OSString * versString = NULL; // do not release
- const char * versCString = NULL; // do not free
- const char * string = NULL; // do not free
-
-#if CONFIG_KXLD
+ struct mach_header ** kxldHeaderPtr = NULL;// do not free
+ struct mach_header * kxld_header = NULL;// xxx - need to free here?
+ OSData * theExecutable = NULL;// do not release
+ OSString * versString = NULL;// do not release
+ const char * versCString = NULL;// do not free
+ const char * string = NULL;// do not free
unsigned int i;
- uint32_t numDirectDependencies = 0;
- kern_return_t kxldResult;
- KXLDDependency * kxlddeps = NULL; // must kfree
- uint32_t num_kxlddeps = 0;
- struct mach_header ** kxldHeaderPtr = NULL; // do not free
- struct mach_header * kxld_header = NULL; // xxx - need to free here?
-#endif // CONFIG_KXLD
/* We need the version string for a variety of bits below.
*/
@@ -7230,24 +5485,12 @@
}
}
-#if defined(__x86_64__) || defined(__i386__)
- if (flags.resetSegmentsFromVnode) {
- /* Fixup the chains and slide the mach headers */
- kernel_mach_header_t *mh = (kernel_mach_header_t *)kmod_info->address;
-
- if (i386_slide_individual_kext(mh, PE_get_kc_slide(kc_type)) != KERN_SUCCESS) {
- result = kOSKextReturnValidation;
- goto finish;
- }
- }
-#endif //(__x86_64__) || defined(__i386__)
-
if (isPrelinked()) {
goto register_kmod;
}
/* <rdar://problem/21444003> all callers must be entitled */
- if (FALSE == IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement)) {
+ if (FALSE == IOTaskHasEntitlement(current_task(), kOSKextManagementEntitlement)) {
OSKextLog(this,
kOSKextLogErrorLevel | kOSKextLogLoadFlag,
"Not entitled to link kext '%s'",
@@ -7271,20 +5514,19 @@
}
if (isInterface()) {
- OSSharedPtr<OSData> executableCopy = OSData::withData(theExecutable);
- if (executableCopy) {
- setLinkedExecutable(executableCopy.get());
- }
+ OSData *executableCopy = OSData::withData(theExecutable);
+ setLinkedExecutable(executableCopy);
+ executableCopy->release();
goto register_kmod;
}
-#if CONFIG_KXLD
numDirectDependencies = getNumDependencies();
if (flags.hasBleedthrough) {
linkDependencies = dependencies;
+ linkDependencies->retain();
} else {
- linkDependencies = OSArray::withArray(dependencies.get());
+ linkDependencies = OSArray::withArray(dependencies);
if (!linkDependencies) {
OSKextLog(this,
kOSKextLogErrorLevel |
@@ -7297,7 +5539,7 @@
for (i = 0; i < numDirectDependencies; ++i) {
OSKext * dependencyKext = OSDynamicCast(OSKext,
dependencies->getObject(i));
- dependencyKext->addBleedthroughDependencies(linkDependencies.get());
+ dependencyKext->addBleedthroughDependencies(linkDependencies);
}
}
@@ -7311,7 +5553,7 @@
goto finish;
}
- kxlddeps = kalloc_type_tag(KXLDDependency, num_kxlddeps, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
+ kxlddeps = (KXLDDependency *)kalloc_tag(num_kxlddeps * sizeof(*kxlddeps), VM_KERN_MEMORY_OSKEXT);
if (!kxlddeps) {
OSKextLog(this,
kOSKextLogErrorLevel |
@@ -7326,17 +5568,17 @@
OSKext * dependency = OSDynamicCast(OSKext, linkDependencies->getObject(i));
if (dependency->isInterface()) {
- OSKext *interfaceTargetKext = NULL; //do not release
- OSData * interfaceTarget = NULL; //do not release
+ OSKext *interfaceTargetKext = NULL;
+ OSData * interfaceTarget = NULL;
if (dependency->isKernelComponent()) {
interfaceTargetKext = sKernelKext;
- interfaceTarget = sKernelKext->linkedExecutable.get();
+ interfaceTarget = sKernelKext->linkedExecutable;
} else {
interfaceTargetKext = OSDynamicCast(OSKext,
dependency->dependencies->getObject(0));
- interfaceTarget = interfaceTargetKext->linkedExecutable.get();
+ interfaceTarget = interfaceTargetKext->linkedExecutable;
}
if (!interfaceTarget) {
@@ -7352,13 +5594,8 @@
kxlddeps[i].kext_size = interfaceTarget->getLength();
kxlddeps[i].kext_name = strdup(interfaceTargetKext->getIdentifierCString());
- if (dependency->linkedExecutable != NULL) {
- kxlddeps[i].interface = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
- kxlddeps[i].interface_size = dependency->linkedExecutable->getLength();
- } else {
- kxlddeps[i].interface = (u_char *) NULL;
- kxlddeps[i].interface_size = 0;
- }
+ kxlddeps[i].interface = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
+ kxlddeps[i].interface_size = dependency->linkedExecutable->getLength();
kxlddeps[i].interface_name = strdup(dependency->getIdentifierCString());
} else {
kxlddeps[i].kext = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
@@ -7415,20 +5652,12 @@
flush_dcache(kmod_info->address, kmod_info->size, false);
invalidate_icache(kmod_info->address, kmod_info->size, false);
#endif
-
-#else // !CONFIG_KXLD
- OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag,
- "Refusing to link non-prelinked kext: %s (no kxld support)", getIdentifierCString());
- result = kOSKextReturnLinkError;
- goto finish;
-#endif // CONFIG_KXLD
-
register_kmod:
if (isInterface()) {
/* Whip up a fake kmod_info entry for the interface kext.
*/
- kmod_info = kalloc_type(kmod_info_t, (zalloc_flags_t)(Z_WAITOK | Z_ZERO));
+ kmod_info = (kmod_info_t *)kalloc_tag(sizeof(kmod_info_t), VM_KERN_MEMORY_OSKEXT);
if (!kmod_info) {
result = KERN_MEMORY_ERROR;
goto finish;
@@ -7436,6 +5665,8 @@
/* A pseudokext has almost nothing in its kmod_info struct.
*/
+ bzero(kmod_info, sizeof(kmod_info_t));
+
kmod_info->info_version = KMOD_INFO_VERSION;
/* An interface kext doesn't have a linkedExecutable, so save a
@@ -7446,7 +5677,7 @@
}
kmod_info->id = loadTag = sNextLoadTag++;
- kmod_info->reference_count = 0; // KMOD_DECL... sets it to -1 (invalid).
+ kmod_info->reference_count = 0; // KMOD_DECL... sets it to -1 (invalid).
/* Stamp the bundle ID and version from the OSKext over anything
* resident inside the kmod_info.
@@ -7461,12 +5692,14 @@
*/
num_kmod_refs = getNumDependencies();
if (num_kmod_refs) {
- kmod_info->reference_list = kalloc_type_tag(kmod_reference_t,
- num_kmod_refs, Z_WAITOK_ZERO, VM_KERN_MEMORY_OSKEXT);
+ kmod_info->reference_list = (kmod_reference_t *)kalloc_tag(
+ num_kmod_refs * sizeof(kmod_reference_t), VM_KERN_MEMORY_OSKEXT);
if (!kmod_info->reference_list) {
result = KERN_MEMORY_ERROR;
goto finish;
}
+ bzero(kmod_info->reference_list,
+ num_kmod_refs * sizeof(kmod_reference_t));
for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
OSKext * refKext = OSDynamicCast(OSKext, dependencies->getObject(refIndex));
@@ -7477,36 +5710,6 @@
ref->next = kmod_info->reference_list + refIndex + 1;
}
}
- }
-
- if (kmod_info->hdr_size > UINT32_MAX) {
- OSKextLog(this,
- kOSKextLogErrorLevel |
- kOSKextLogLoadFlag,
-#if __LP64__
- "Kext %s header size is too large (%lu > UINT32_MAX).",
-#else
- "Kext %s header size is too large (%u > UINT32_MAX).",
-#endif
- kmod_info->name,
- kmod_info->hdr_size);
- result = KERN_FAILURE;
- goto finish;
- }
-
- if (kmod_info->size > UINT32_MAX) {
- OSKextLog(this,
- kOSKextLogErrorLevel |
- kOSKextLogLoadFlag,
-#if __LP64__
- "Kext %s size is too large (%lu > UINT32_MAX).",
-#else
- "Kext %s size is too large (%u > UINT32_MAX).",
-#endif
- kmod_info->name,
- kmod_info->size);
- result = KERN_FAILURE;
- goto finish;
}
if (!isInterface() && linkedExecutable) {
@@ -7520,13 +5723,10 @@
(unsigned)kmod_info->id);
}
- /* VM protections and wiring for the Aux KC are done at collection loading time */
- if (kc_type != KCKindAuxiliary || flags.resetSegmentsFromVnode) {
- /* if prelinked and primary KC, VM protections are already set */
- result = setVMAttributes(!isPrelinked() || flags.resetSegmentsFromVnode, true);
- if (result != KERN_SUCCESS) {
- goto finish;
- }
+ /* if prelinked, VM protections are already set */
+ result = setVMAttributes(!isPrelinked(), true);
+ if (result != KERN_SUCCESS) {
+ goto finish;
}
#if KASAN
@@ -7549,8 +5749,8 @@
result = kOSReturnSuccess;
finish:
-
-#if CONFIG_KXLD
+ OSSafeReleaseNULL(linkDependencies);
+
/* Clear up locally allocated dependency info.
*/
for (i = 0; i < num_kxlddeps; ++i) {
@@ -7558,17 +5758,16 @@
if (kxlddeps[i].kext_name) {
size = 1 + strlen(kxlddeps[i].kext_name);
- kfree_data(kxlddeps[i].kext_name, size);
+ kfree(kxlddeps[i].kext_name, size);
}
if (kxlddeps[i].interface_name) {
size = 1 + strlen(kxlddeps[i].interface_name);
- kfree_data(kxlddeps[i].interface_name, size);
+ kfree(kxlddeps[i].interface_name, size);
}
}
if (kxlddeps) {
- kfree_type(KXLDDependency, num_kxlddeps, kxlddeps);
- }
-#endif // CONFIG_KXLD
+ kfree(kxlddeps, (num_kxlddeps * sizeof(*kxlddeps)));
+ }
/* We no longer need the unrelocated executable (which the linker
* has altered anyhow).
@@ -7583,60 +5782,20 @@
getIdentifierCString());
if (kmod_info && kmod_info->reference_list) {
- kfree_type(kmod_reference_t, num_kmod_refs,
- kmod_info->reference_list);
+ kfree(kmod_info->reference_list,
+ num_kmod_refs * sizeof(kmod_reference_t));
}
if (isInterface()) {
- kfree_type(kmod_info_t, kmod_info);
- kmod_info = NULL;
- }
- if (kc_type == KCKindUnknown) {
- kmod_info = NULL;
- if (linkedExecutable) {
- linkedExecutable.reset();
- }
+ kfree(kmod_info, sizeof(kmod_info_t));
+ }
+ kmod_info = NULL;
+ if (linkedExecutable) {
+ linkedExecutable->release();
+ linkedExecutable = NULL;
}
}
return result;
-}
-
-/* static */
-void
-OSKext::jettisonFileSetLinkeditSegment(kernel_mach_header_t *mh)
-{
- kernel_segment_command_t *linkeditseg = NULL;
-
- linkeditseg = getsegbynamefromheader(mh, SEG_LINKEDIT);
- if (linkeditseg == NULL) {
- panic("FileSet booted with no Linkedit segment");
- }
-
-#if VM_MAPPED_KEXTS
- /* BootKC on x86_64 is not vm mapped */
- ml_static_mfree(linkeditseg->vmaddr, linkeditseg->vmsize);
-
- OSKextLog(/* kext */ NULL,
- kOSKextLogProgressLevel |
- kOSKextLogGeneralFlag,
- "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu",
- linkeditseg->vmaddr, linkeditseg->vmsize);
-#else
- /* BootKC on arm64 is not vm mapped, but is slid */
-#if !CONFIG_SPTM
- vm_offset_t linkedit_vmaddr = ml_static_ptovirt((vm_offset_t)(linkeditseg->vmaddr - gVirtBase + gPhysBase));
-#else
- vm_offset_t linkedit_vmaddr = linkeditseg->vmaddr;
-#endif
-
- ml_static_mfree(linkedit_vmaddr, (vm_size_t)linkeditseg->vmsize);
-
- OSKextLog(/* kext */ NULL,
- kOSKextLogProgressLevel |
- kOSKextLogGeneralFlag,
- "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu",
- (unsigned long long)linkedit_vmaddr, (unsigned long long)linkeditseg->vmsize);
-#endif /* VM_MAPPED_KEXTS */
}
/*********************************************************************
@@ -7652,12 +5811,7 @@
kernel_segment_command_t * linkedit = NULL;
vm_offset_t start;
vm_size_t linkeditsize, kextsize;
- OSSharedPtr<OSData> data;
- kc_format format = KCFormatUnknown;
-
- if (isInFileset()) {
- return;
- }
+ OSData * data = NULL;
#if NO_KEXTD
/* We can free symbol tables for all embedded kexts because we don't
@@ -7690,10 +5844,7 @@
kextsize = kmod_info->size - linkeditsize;
start = linkedit->vmaddr;
- if (kextsize > UINT_MAX) {
- goto finish;
- }
- data = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)kextsize);
+ data = OSData::withBytesNoCopy((void *)kmod_info->address, kextsize);
if (!data) {
goto finish;
}
@@ -7702,22 +5853,14 @@
*/
kmod_info->size = kextsize;
- /*
- * Fileset KCs are mapped as a whole by iBoot.
- * Individual kext executables should not be unmapped by xnu
- * Doing so may result in panics like rdar://85419651
- */
- if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) {
- data->setDeallocFunction(NULL);
- } else { // Not from a Fileset KC
#if VM_MAPPED_KEXTS
- data->setDeallocFunction(osdata_kext_free);
+ data->setDeallocFunction(osdata_kext_free);
#else
- data->setDeallocFunction(osdata_phys_free);
+ data->setDeallocFunction(osdata_phys_free);
#endif
- }
linkedExecutable->setDeallocFunction(NULL);
- linkedExecutable = os::move(data);
+ linkedExecutable->release();
+ linkedExecutable = data;
flags.jettisonLinkeditSeg = 1;
/* Free the linkedit segment.
@@ -7750,10 +5893,6 @@
return;
}
mh = (kernel_mach_header_t *)kmod_info->address;
-
- if (isInFileset()) {
- return;
- }
dataSeg = getsegbynamefromheader(mh, SEG_DATA);
if (dataSeg == NULL) {
@@ -7804,7 +5943,8 @@
"that already has one (%s).\n",
getIdentifierCString());
}
- linkedExecutable.reset(anExecutable, OSRetain);
+ linkedExecutable = anExecutable;
+ linkedExecutable->retain();
return;
}
@@ -7823,7 +5963,7 @@
IORecursiveLockLock(sKextLock);
for (i = 0; i < count; i++) {
- OSKext * thisKext = NULL; // do not release
+ OSKext * thisKext = NULL;// do not release
thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
if (!thisKext || !thisKext->isExecutable()) {
@@ -7854,20 +5994,6 @@
if (!flags.dtraceInitialized && (dtrace_modload != NULL)) {
uint32_t modflag = 0;
OSObject * forceInit = getPropertyForHostArch("OSBundleForceDTraceInit");
-
- if (!sKeepSymbols && kc_type == KCKindPrimary) {
- if (forceInit == kOSBooleanTrue) {
- OSKextLog(this,
- kOSKextLogBasicLevel |
- kOSKextLogGeneralFlag,
- "Ignoring OSBundleForceDTraceInit for Boot KC Kext %s",
- getIdentifierCString());
- forceInit = kOSBooleanFalse;
- }
- /* Linkedit segment of the Boot KC is gone, make sure fbt_provide_module don't use kernel symbols */
- modflag |= KMOD_DTRACE_NO_KERNEL_SYMS;
- }
-
if (forceInit == kOSBooleanTrue) {
modflag |= KMOD_DTRACE_FORCE_INIT;
}
@@ -7905,40 +6031,34 @@
#if defined(__arm__) || defined(__arm64__)
static inline kern_return_t
OSKext_protect(
- kernel_mach_header_t *kext_mh,
vm_map_t map,
vm_map_offset_t start,
- vm_map_size_t size,
+ vm_map_offset_t end,
vm_prot_t new_prot,
- boolean_t set_max,
- kc_kind_t kc_type)
-{
- vm_map_offset_t end = start + size;
-
-#pragma unused(kext_mh,map,kc_type)
- assert(map == kernel_map); // we can handle KEXTs arising from the PRELINK segment and no others
+ boolean_t set_max)
+{
+#pragma unused(map)
+ assert(map == kernel_map); // we can handle KEXTs arising from the PRELINK segment and no others
assert(start <= end);
if (start >= end) {
- return KERN_SUCCESS; // Punt segments of length zero (e.g., headers) or less (i.e., blunders)
+ return KERN_SUCCESS; // Punt segments of length zero (e.g., headers) or less (i.e., blunders)
} else if (set_max) {
- return KERN_SUCCESS; // Punt set_max, as there's no mechanism to record that state
+ return KERN_SUCCESS; // Punt set_max, as there's no mechanism to record that state
} else {
- return ml_static_protect(start, size, new_prot);
+ return ml_static_protect(start, end - start, new_prot);
}
}
static inline kern_return_t
OSKext_wire(
- kernel_mach_header_t *kext_mh,
vm_map_t map,
vm_map_offset_t start,
vm_map_offset_t end,
vm_prot_t access_type,
- boolean_t user_wire,
- kc_kind_t kc_type)
-{
-#pragma unused(kext_mh,map,start,end,access_type,user_wire,kc_type)
- return KERN_SUCCESS; // No-op as PRELINK kexts are cemented into physical memory at boot
+ boolean_t user_wire)
+{
+#pragma unused(map,start,end,access_type,user_wire)
+ return KERN_SUCCESS; // No-op as PRELINK kexts are cemented into physical memory at boot
}
#else
#error Unrecognized architecture
@@ -7946,43 +6066,26 @@
#else
static inline kern_return_t
OSKext_protect(
- kernel_mach_header_t *kext_mh,
vm_map_t map,
vm_map_offset_t start,
- vm_map_size_t size,
+ vm_map_offset_t end,
vm_prot_t new_prot,
- boolean_t set_max,
- kc_kind_t kc_type)
-{
- vm_map_offset_t end = start + size;
-
- if (start == end) { // 10538581
+ boolean_t set_max)
+{
+ if (start == end) { // 10538581
return KERN_SUCCESS;
}
- if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) {
- /*
- * XXX: This will probably need to be different for AuxKC and
- * pageableKC!
- */
- return ml_static_protect(start, size, new_prot);
- }
- return mach_vm_protect(map, start, size, set_max, new_prot);
+ return vm_map_protect(map, start, end, new_prot, set_max);
}
static inline kern_return_t
OSKext_wire(
- kernel_mach_header_t *kext_mh,
vm_map_t map,
vm_map_offset_t start,
vm_map_offset_t end,
vm_prot_t access_type,
- boolean_t user_wire,
- kc_kind_t kc_type)
-{
- if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) {
- /* TODO: we may need to hook this for the pageableKC */
- return KERN_SUCCESS;
- }
+ boolean_t user_wire)
+{
return vm_map_wire_kernel(map, start, end, access_type, VM_KERN_MEMORY_KEXT, user_wire);
}
#endif
@@ -7992,11 +6095,8 @@
{
vm_map_t kext_map = NULL;
kernel_segment_command_t * seg = NULL;
- vm_map_offset_t start_protect = 0;
- vm_map_offset_t start_wire = 0;
- vm_map_offset_t end_protect = 0;
- vm_map_size_t size_protect = 0;
- vm_map_offset_t end_wire = 0;
+ vm_map_offset_t start = 0;
+ vm_map_offset_t end = 0;
OSReturn result = kOSReturnError;
if (isInterface() || !declaresExecutable() || flags.builtin) {
@@ -8023,18 +6123,11 @@
result = KERN_SUCCESS;
goto finish;
}
-
- if (isInFileset() && kc_type != KCKindPageable) {
- // kexts in filesets have protections setup as part of collection loading
- result = KERN_SUCCESS;
- goto finish;
- }
#endif
/* Protect the headers as read-only; they do not need to be wired */
- result = (protect) ? OSKext_protect((kernel_mach_header_t *)kmod_info->address,
- kext_map, kmod_info->address,
- kmod_info->hdr_size, VM_PROT_READ, TRUE, kc_type)
+ result = (protect) ? OSKext_protect(kext_map, kmod_info->address,
+ kmod_info->address + kmod_info->hdr_size, VM_PROT_READ, TRUE)
: KERN_SUCCESS;
if (result != KERN_SUCCESS) {
goto finish;
@@ -8049,36 +6142,11 @@
assert((seg->vmsize & PAGE_MASK) == 0);
#endif
- /*
- * For the non page aligned segments, the range calculation for protection
- * and wiring differ as follows:
- *
- * Protection: The non page aligned data at the start or at the end of the
- * segment is excluded from the protection. This exclusion is needed to make
- * sure OSKext_protect is not called twice on same page, if the page is shared
- * between two segments.
- *
- * Wiring: The non page aligned data at the start or at the end of the
- * segment is included in the wiring range, this inclusion is needed to make sure
- * all the data of the segment is wired.
- */
- start_protect = round_page(seg->vmaddr);
- end_protect = trunc_page(seg->vmaddr + seg->vmsize);
- size_protect = end_protect - start_protect;
-
- start_wire = trunc_page(seg->vmaddr);
- end_wire = round_page(seg->vmaddr + seg->vmsize);
-
- /*
- * Linkedit and Linkinfo for the Pageable KC and the Aux KC are shared
- * across kexts and data from kexts is not page aligned
- */
- if (protect && (end_protect > start_protect) &&
- ((strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0 &&
- strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) != 0) ||
- (kc_type != KCKindPageable && kc_type != KCKindAuxiliary))) {
- result = OSKext_protect((kernel_mach_header_t *)kmod_info->address,
- kext_map, start_protect, size_protect, seg->maxprot, TRUE, kc_type);
+ start = round_page(seg->vmaddr);
+ end = trunc_page(seg->vmaddr + seg->vmsize);
+
+ if (protect) {
+ result = OSKext_protect(kext_map, start, end, seg->maxprot, TRUE);
if (result != KERN_SUCCESS) {
OSKextLog(this,
kOSKextLogErrorLevel |
@@ -8089,8 +6157,7 @@
goto finish;
}
- result = OSKext_protect((kernel_mach_header_t *)kmod_info->address,
- kext_map, start_protect, size_protect, seg->initprot, FALSE, kc_type);
+ result = OSKext_protect(kext_map, start, end, seg->initprot, FALSE);
if (result != KERN_SUCCESS) {
OSKextLog(this,
kOSKextLogErrorLevel |
@@ -8103,8 +6170,7 @@
}
if (segmentShouldBeWired(seg) && wire) {
- result = OSKext_wire((kernel_mach_header_t *)kmod_info->address,
- kext_map, start_wire, end_wire, seg->initprot, FALSE, kc_type);
+ result = OSKext_wire(kext_map, start, end, seg->initprot, FALSE);
if (result != KERN_SUCCESS) {
goto finish;
}
@@ -8122,8 +6188,7 @@
boolean_t
OSKext::segmentShouldBeWired(kernel_segment_command_t *seg)
{
- return sKeepSymbols || (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) &&
- strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)));
+ return sKeepSymbols || strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname));
}
/*********************************************************************
@@ -8139,11 +6204,8 @@
mach_vm_address_t address = 0;
mach_vm_size_t size = 0;
uint32_t depth = 0;
- uint64_t kext_segbase = 0;
- uint64_t kext_segsize = 0;
mach_msg_type_number_t count;
vm_region_submap_short_info_data_64_t info;
- uintptr_t kext_slide = PE_get_kc_slide(kc_type);
if (flags.builtin) {
return kOSReturnSuccess;
@@ -8185,16 +6247,10 @@
kext_map = kext_get_vm_map(kmod_info);
depth = (kernel_map == kext_map) ? 1 : 2;
- if (isInFileset()) {
-#if defined(HAS_APPLE_PAC)
- address = (mach_vm_address_t)ptrauth_auth_data((void*)address, ptrauth_key_function_pointer, 0);
-#endif /* defined(HAS_APPLE_PAC) */
- }
/* Verify that the start/stop function lies within the kext's address range.
*/
- if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO) ||
- isInFileset()) {
+ if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO)) {
/* This will likely be how we deal with split kexts; walk the segments to
* check that the function lies inside one of the segments of this kext.
*/
@@ -8202,8 +6258,6 @@
seg != NULL;
seg = nextsegfromheader((kernel_mach_header_t *)kmod_info->address, seg)) {
if ((address >= seg->vmaddr) && address < (seg->vmaddr + seg->vmsize)) {
- kext_segbase = seg->vmaddr;
- kext_segsize = seg->vmsize;
break;
}
}
@@ -8217,8 +6271,8 @@
getIdentifierCString(),
whichOp,
whichOp,
- (void *)(((uintptr_t)address) - kext_slide),
- (void *)(((uintptr_t)kmod_info->address) - kext_slide));
+ (void *)ml_static_unslide(address),
+ (void *)ml_static_unslide(kmod_info->address));
result = kOSKextReturnBadData;
goto finish;
}
@@ -8235,9 +6289,9 @@
getIdentifierCString(),
whichOp,
whichOp,
- (void *)(((uintptr_t)address) - kext_slide),
- (void *)(((uintptr_t)kmod_info->address) - kext_slide),
- (void *)((((uintptr_t)kmod_info->address) - kext_slide) + kmod_info->size));
+ (void *)ml_static_unslide(address),
+ (void *)ml_static_unslide(kmod_info->address),
+ (void *)(ml_static_unslide(kmod_info->address) + kmod_info->size));
result = kOSKextReturnBadData;
goto finish;
}
@@ -8248,44 +6302,23 @@
* we'll likely have panicked well before any attempt to stop the kext.
*/
if (startFlag) {
- if (!isInFileset() || kc_type != KCKindPrimary) {
- /*
- * Verify that the start/stop function is executable.
- */
- kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth,
- (vm_region_recurse_info_t)&info, &count);
- if (kern_result != KERN_SUCCESS) {
- OSKextLog(this,
- kOSKextLogErrorLevel |
- kOSKextLogLoadFlag,
- "Kext %s - bad %s pointer %p.",
- getIdentifierCString(),
- whichOp, (void *)ml_static_unslide(address));
- result = kOSKextReturnBadData;
- goto finish;
- }
- } else {
- /*
- * Since kexts loaded from the primary KC are held in memory
- * allocated by efiboot, we cannot use mach_vm_region_recurse() to
- * discover that memory's protection flags. Instead, we need to
- * get that information from the kernel pmap itself. Above, we
- * (potentially) saved the size of the segment in which the address
- * in question was located. If we have a non-zero size, verify
- * that all pages in the (address, address + kext_segsize) range
- * are marked executable. If we somehow did not record the size
- * (or the base) just verify the single page that includes the address.
- */
- if (kext_segbase == 0 || kext_segsize == 0) {
- kext_segbase = address & ~(uint64_t)PAGE_MASK;
- kext_segsize = PAGE_SIZE;
- }
+ /* Verify that the start/stop function is executable.
+ */
+ kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth,
+ (vm_region_recurse_info_t)&info, &count);
+ if (kern_result != KERN_SUCCESS) {
+ OSKextLog(this,
+ kOSKextLogErrorLevel |
+ kOSKextLogLoadFlag,
+ "Kext %s - bad %s pointer %p.",
+ getIdentifierCString(),
+ whichOp, (void *)ml_static_unslide(address));
+ result = kOSKextReturnBadData;
+ goto finish;
}
#if VM_MAPPED_KEXTS
- if (((!isInFileset() || kc_type != KCKindPrimary) && !(info.protection & VM_PROT_EXECUTE)) ||
- ((isInFileset() && kc_type == KCKindPrimary) &&
- ml_static_verify_page_protections(kext_segbase, kext_segsize, VM_PROT_EXECUTE) != KERN_SUCCESS)) {
+ if (!(info.protection & VM_PROT_EXECUTE)) {
OSKextLog(this,
kOSKextLogErrorLevel |
kOSKextLogLoadFlag,
@@ -8321,10 +6354,6 @@
OSKext::verifySegmentMapping(kernel_segment_command_t *seg)
{
mach_vm_address_t address = 0;
-
- if (seg->vmsize > UINT32_MAX) {
- return false;
- }
if (!segmentShouldBeWired(seg)) {
return true;
@@ -8357,7 +6386,7 @@
struct firehose_trace_uuid_info_s uuid_info_s;
firehose_trace_uuid_info_t uuid_info = &uuid_info_s;
size_t uuid_info_len = sizeof(struct firehose_trace_uuid_info_s);
- OSSharedPtr<OSData> uuid_data;
+ OSData *uuid_data;
stamp = firehose_tracepoint_time(firehose_activity_flags_default);
trace_id.ftid_value = FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata, _firehose_tracepoint_type_metadata_kext, (firehose_tracepoint_flags_t)0, code);
@@ -8365,6 +6394,7 @@
uuid_data = aKext->copyTextUUID();
if (uuid_data) {
memcpy(uuid_info->ftui_uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_info->ftui_uuid));
+ OSSafeReleaseNULL(uuid_data);
}
uuid_info->ftui_size = size;
@@ -8373,7 +6403,7 @@
} else {
uuid_info->ftui_address = ml_static_unslide(address);
}
- os_log_encoded_metadata(trace_id, stamp, uuid_info, uuid_info_len);
+ firehose_trace_metadata(firehose_stream_metadata, trace_id, stamp, uuid_info, uuid_info_len);
return;
}
@@ -8457,7 +6487,7 @@
"Not starting %s - dependency %s not started yet.",
getIdentifierCString(),
dependency->getIdentifierCString());
- result = kOSKextReturnStartStopError; // xxx - make new return?
+ result = kOSKextReturnStartStopError; // xxx - make new return?
goto finish;
}
}
@@ -8497,7 +6527,7 @@
/* result not actually used */ kOSKextReturnStartStopError,
/* invokeFlag */ false);
OSKextLog(this,
- kOSKextLogWarningLevel |
+ kOSKextLogProgressLevel |
kOSKextLogLoadFlag,
"Kext %s did not start (return code 0x%x).",
getIdentifierCString(), result);
@@ -8516,14 +6546,14 @@
bool checkClassesFlag)
{
bool result = false;
- OSKext * aKext = NULL; // do not release
+ OSKext * aKext = NULL;// do not release
IORecursiveLockLock(sKextLock);
aKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
if (!aKext) {
- goto finish; // can't unload what's not loaded
+ goto finish; // can't unload what's not loaded
}
if (aKext->isLoaded()) {
@@ -8648,7 +6678,6 @@
unsigned int index;
uint32_t num_kmod_refs = 0;
OSKextAccount * freeAccount;
- bool in_fileset = false;
if (!sUnloadEnabled) {
OSKextLog(this,
@@ -8661,10 +6690,6 @@
goto finish;
}
- // cache this result so we don't need to access the kmod_info after
- // it's been potentially free'd
- in_fileset = isInFileset();
-
/* Refuse to unload if we have clients or instances. It is up to
* the caller to make sure those aren't true.
*/
@@ -8673,14 +6698,14 @@
OSKextLog(this,
kOSKextLogErrorLevel |
kOSKextLogKextBookkeepingFlag,
- "Can't unload kext %s; outstanding references %d (linkage or tracking object).",
- getIdentifierCString(), getRetainCount());
+ "Can't unload kext %s; outstanding references (linkage or tracking object).",
+ getIdentifierCString());
result = kOSKextReturnInUse;
goto finish;
}
if (isDriverKit()) {
- index = sLoadedDriverKitKexts->getNextIndexOfObject(this, 0);
+ index = sLoadedKexts->getNextIndexOfObject(this, 0);
if (index != (unsigned int)-1) {
sLoadedDriverKitKexts->removeObject(index);
OSKextLogKextInfo(this, loadTag, 1, firehose_tracepoint_code_unload);
@@ -8698,7 +6723,7 @@
goto finish;
}
- if (metaClasses && !OSMetaClass::removeClasses(metaClasses.get())) {
+ if (metaClasses && !OSMetaClass::removeClasses(metaClasses)) {
OSKextLog(this,
kOSKextLogErrorLevel |
kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
@@ -8785,7 +6810,7 @@
sLoadedKexts->getObject(index - 1));
nextKext->kmod_info->next = gapKext->kmod_info;
- } else { /* index == 0 */
+ } else { /* index == 0 */
nextKext->kmod_info->next = NULL;
}
}
@@ -8794,7 +6819,7 @@
if (lastKext && !lastKext->isKernel()) {
kmod = lastKext->kmod_info;
} else {
- kmod = NULL; // clear the global kmod variable
+ kmod = NULL; // clear the global kmod variable
}
}
@@ -8808,8 +6833,8 @@
kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
ref->info->reference_count--;
}
- kfree_type(kmod_reference_t, num_kmod_refs,
- kmod_info->reference_list);
+ kfree(kmod_info->reference_list,
+ num_kmod_refs * sizeof(kmod_reference_t));
}
#if CONFIG_DTRACE
@@ -8819,22 +6844,16 @@
notifyKextUnloadObservers(this);
freeAccount = NULL;
- lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
+ IOSimpleLockLock(sKextAccountsLock);
account->kext = NULL;
if (account->site.tag) {
account->site.flags |= VM_TAG_UNLOAD;
} else {
freeAccount = account;
}
-
-#if DEVELOPMENT || DEBUG
- assertf(account->task_refgrp.grp_count == 0,
- "unloading a kext with active task references");
-#endif /* DEVELOPMENT || DEBUG */
-
- lck_ticket_unlock(sKextAccountsLock);
+ IOSimpleLockUnlock(sKextAccountsLock);
if (freeAccount) {
- IOFreeType(freeAccount, OSKextAccount);
+ IODelete(freeAccount, OSKextAccount, 1);
}
/* Unwire and free the linked executable.
@@ -8845,7 +6864,7 @@
#endif
#if VM_MAPPED_KEXTS
- if (!isInterface() && (!in_fileset || flags.resetSegmentsFromVnode)) {
+ if (!isInterface()) {
kernel_segment_command_t *seg = NULL;
vm_map_t kext_map = kext_get_vm_map(kmod_info);
@@ -8868,11 +6887,8 @@
seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
while (seg) {
if (segmentShouldBeWired(seg)) {
- vm_map_offset_t start_wire = trunc_page(seg->vmaddr);
- vm_map_offset_t end_wire = round_page(seg->vmaddr + seg->vmsize);
-
- result = vm_map_unwire(kext_map, start_wire,
- end_wire, FALSE);
+ result = vm_map_unwire(kext_map, seg->vmaddr,
+ seg->vmaddr + seg->vmsize, FALSE);
if (result != KERN_SUCCESS) {
OSKextLog(this,
kOSKextLogErrorLevel |
@@ -8886,43 +6902,19 @@
seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
}
-#if defined(__x86_64__) || defined(__i386__)
- if (in_fileset && flags.resetSegmentsFromVnode) {
- IORecursiveLockLock(sKextLock);
- resetKCFileSetSegments();
- IORecursiveLockUnlock(sKextLock);
- }
-#endif // (__x86_64__) || defined(__i386__)
- }
-#endif /* VM_MAPPED_KEXTS */
- if (flags.resetSegmentsFromImmutableCopy) {
- result = resetMutableSegments();
- if (result != kOSReturnSuccess) {
- OSKextLog(this,
- kOSKextLogErrorLevel |
- kOSKextLogLoadFlag,
- "Failed to reset kext %s.",
- getIdentifierCString());
- result = kOSKextReturnInternalError;
- goto finish;
- }
- }
- if (kc_type == KCKindUnknown) {
- linkedExecutable.reset();
- }
+ }
+#endif
+ OSSafeReleaseNULL(linkedExecutable);
}
/* An interface kext has a fake kmod_info that was allocated,
* so we have to free it.
*/
if (isInterface()) {
- kfree_type(kmod_info_t, kmod_info);
- kmod_info = NULL;
- }
-
- if (!in_fileset) {
- kmod_info = NULL;
- }
+ kfree(kmod_info, sizeof(kmod_info_t));
+ }
+
+ kmod_info = NULL;
flags.loaded = false;
flushDependencies();
@@ -8933,10 +6925,10 @@
* kernel cache. 9055303
*/
if (isPrelinked()) {
- if (!_OSKextInUnloadedPrelinkedKexts(bundleID.get())) {
+ if (!_OSKextInUnloadedPrelinkedKexts(bundleID)) {
IORecursiveLockLock(sKextLock);
if (sUnloadedPrelinkedKexts) {
- sUnloadedPrelinkedKexts->setObject(bundleID.get());
+ sUnloadedPrelinkedKexts->setObject(bundleID);
}
IORecursiveLockUnlock(sKextLock);
}
@@ -8947,7 +6939,7 @@
"Kext %s unloaded.", getIdentifierCString());
queueKextNotification(kKextRequestPredicateUnloadNotification,
- OSDynamicCast(OSString, bundleID.get()), getDextUniqueID());
+ OSDynamicCast(OSString, bundleID));
finish:
OSKext::saveLoadedKextPanicList();
@@ -8964,11 +6956,10 @@
OSReturn
OSKext::queueKextNotification(
const char * notificationName,
- OSString * kextIdentifier,
- OSData * dextUniqueIdentifier)
+ OSString * kextIdentifier)
{
OSReturn result = kOSReturnError;
- OSSharedPtr<OSDictionary> loadRequest;
+ OSDictionary * loadRequest = NULL;// must release
if (!kextIdentifier) {
result = kOSKextReturnInvalidArgument;
@@ -8978,42 +6969,35 @@
/* Create a new request unless one is already sitting
* in sKernelRequests for this bundle identifier
*/
- result = _OSKextCreateRequest(notificationName, loadRequest);
+ result = _OSKextCreateRequest(notificationName, &loadRequest);
if (result != kOSReturnSuccess) {
goto finish;
}
- if (!_OSKextSetRequestArgument(loadRequest.get(),
+ if (!_OSKextSetRequestArgument(loadRequest,
kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
result = kOSKextReturnNoMemory;
goto finish;
}
- if (NULL != dextUniqueIdentifier) {
- if (!_OSKextSetRequestArgument(loadRequest.get(),
- kKextRequestArgumentDriverUniqueIdentifier, dextUniqueIdentifier)) {
- result = kOSKextReturnNoMemory;
- goto finish;
- }
- }
- if (!sKernelRequests->setObject(loadRequest.get())) {
+ if (!sKernelRequests->setObject(loadRequest)) {
result = kOSKextReturnNoMemory;
goto finish;
}
- /* We might want to only queue the notification if the IOKit daemon is active,
+ /* We might want to only queue the notification if kextd is active,
* but that wouldn't work for embedded. Note that we don't care if
* the ping immediately succeeds here so don't do anything with the
* result of this call.
*/
- OSKext::pingIOKitDaemon();
+ OSKext::pingKextd();
result = kOSReturnSuccess;
finish:
+ OSSafeReleaseNULL(loadRequest);
+
return result;
}
-
-#if CONFIG_KXLD
/*********************************************************************
*********************************************************************/
static void
@@ -9095,17 +7079,6 @@
return;
}
-#else // !CONFIG_KXLD
-
-/* static */
-void
-OSKext::considerDestroyingLinkContext(void)
-{
- return;
-}
-
-#endif // CONFIG_KXLD
-
#if PRAGMA_MARK
#pragma mark Autounload
#endif
@@ -9118,17 +7091,6 @@
OSKext::autounloadKext(OSKext * aKext)
{
OSReturn result = kOSKextReturnInUse;
-
-#if NO_KEXTD
- /*
- * Do not unload prelinked kexts on platforms that do not have an
- * IOKit daemon as there is no way to reload the kext or restart
- * matching.
- */
- if (aKext->isPrelinked()) {
- goto finish;
- }
-#endif /* defined(__x86_64__) */
/* Check for external references to this kext (usu. dependents),
* instances of defined classes (or classes derived from them),
@@ -9201,17 +7163,15 @@
do {
OSDictionary * callbackRecord = OSDynamicCast(OSDictionary,
sRequestCallbackRecords->getObject(i));
- if (callbackRecord) {
- OSBoolean * stale = OSDynamicCast(OSBoolean,
- callbackRecord->getObject(kKextRequestStaleKey));
-
- if (stale == kOSBooleanTrue) {
- OSKext::invokeRequestCallback(callbackRecord,
- kOSKextReturnTimeout);
- } else {
- callbackRecord->setObject(kKextRequestStaleKey,
- kOSBooleanTrue);
- }
+ OSBoolean * stale = OSDynamicCast(OSBoolean,
+ callbackRecord->getObject(kKextRequestStaleKey));
+
+ if (stale == kOSBooleanTrue) {
+ OSKext::invokeRequestCallback(callbackRecord,
+ kOSKextReturnTimeout);
+ } else {
+ callbackRecord->setObject(kKextRequestStaleKey,
+ kOSBooleanTrue);
}
} while (i--);
}
@@ -9273,11 +7233,7 @@
}
thread_call_cancel(sUnloadCallout);
- if (OSKext::getAutounloadEnabled() && !sSystemSleep
-#if !NO_KEXTD
- && sIOKitDaemonActive
-#endif
- ) {
+ if (OSKext::getAutounloadEnabled() && !sSystemSleep) {
clock_interval_to_deadline(sConsiderUnloadDelay,
1000 * 1000 * 1000, &when);
@@ -9344,8 +7300,6 @@
#if PRAGMA_MARK
#pragma mark Prelinked Kernel
#endif
-
-#ifdef CONFIG_KXLD
/*********************************************************************
* Do not access sConsiderUnloads... variables other than
* sConsiderUnloadsExecuted in this function. They are guarded by a
@@ -9357,9 +7311,9 @@
{
static bool requestedPrelink = false;
OSReturn checkResult = kOSReturnError;
- OSSharedPtr<OSDictionary> prelinkRequest;
- OSSharedPtr<OSCollectionIterator> kextIterator;
- const OSSymbol * thisID = NULL; // do not release
+ OSDictionary * prelinkRequest = NULL;// must release
+ OSCollectionIterator * kextIterator = NULL;// must release
+ const OSSymbol * thisID = NULL;// do not release
bool doRebuild = false;
AbsoluteTime my_abstime;
UInt64 my_ns;
@@ -9373,7 +7327,7 @@
/* no direct return from this point */
IORecursiveLockLock(sKextLock);
- /* We need to wait for the IOKit daemon to get up and running with unloads already done
+ /* We need to wait for kextd to get up and running with unloads already done
* and any new startup kexts loaded.
*/
if (!sConsiderUnloadsExecuted ||
@@ -9418,20 +7372,20 @@
* We will rebuild if any kext is not marked prelinked AND is not in our
* list of prelinked kexts that got unloaded. (see radar 9055303)
*/
- kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
+ kextIterator = OSCollectionIterator::withCollection(sKextsByID);
if (!kextIterator) {
goto finish;
}
while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
- OSKext * thisKext; // do not release
+ OSKext * thisKext;// do not release
thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
if (!thisKext || thisKext->isPrelinked() || thisKext->isKernel()) {
continue;
}
- if (_OSKextInUnloadedPrelinkedKexts(thisKext->bundleID.get())) {
+ if (_OSKextInUnloadedPrelinkedKexts(thisKext->bundleID)) {
continue;
}
/* kext is loaded and was not in current kernel cache so let's rebuild
@@ -9450,33 +7404,24 @@
}
checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestPrelink,
- prelinkRequest);
+ &prelinkRequest);
if (checkResult != kOSReturnSuccess) {
goto finish;
}
- if (!sKernelRequests->setObject(prelinkRequest.get())) {
- goto finish;
- }
-
- OSKext::pingIOKitDaemon();
+ if (!sKernelRequests->setObject(prelinkRequest)) {
+ goto finish;
+ }
+
+ OSKext::pingKextd();
finish:
IORecursiveLockUnlock(sKextLock);
+ OSSafeReleaseNULL(prelinkRequest);
+ OSSafeReleaseNULL(kextIterator);
return;
}
-
-#else /* !CONFIG_KXLD */
-
-void
-OSKext::considerRebuildOfPrelinkedKernel(void)
-{
- /* in a non-dynamic kext loading world, there is never a reason to rebuild */
- return;
-}
-
-#endif /* CONFIG_KXLD */
#if PRAGMA_MARK
#pragma mark Dependencies
@@ -9488,22 +7433,19 @@
OSArray * loopStack)
{
bool result = false;
- OSSharedPtr<OSArray> localLoopStack;
+ OSArray * localLoopStack = NULL;// must release
bool addedToLoopStack = false;
- OSDictionary * libraries = NULL; // do not release
- OSSharedPtr<OSCollectionIterator> libraryIterator;
- OSString * libraryID = NULL; // do not release
- OSKext * libraryKext = NULL; // do not release
+ OSDictionary * libraries = NULL;// do not release
+ OSCollectionIterator * libraryIterator = NULL;// must release
+ OSString * libraryID = NULL;// do not release
+ OSString * infoString = NULL;// do not release
+ OSString * readableString = NULL;// do not release
+ OSKext * libraryKext = NULL;// do not release
bool hasRawKernelDependency = false;
bool hasKernelDependency = false;
bool hasKPIDependency = false;
bool hasPrivateKPIDependency = false;
unsigned int count;
-
-#if CONFIG_KXLD
- OSString * infoString = NULL; // do not release
- OSString * readableString = NULL; // do not release
-#endif // CONFIG_KXLD
/* A kernel component will automatically have this flag set,
* and a loaded kext should also have it set (as should all its
@@ -9532,8 +7474,8 @@
"Kext %s resolving dependencies.",
getIdentifierCString());
- localLoopStack = OSArray::withCapacity(6); // any small capacity will do
- if (!localLoopStack) {
+ loopStack = OSArray::withCapacity(6); // any small capacity will do
+ if (!loopStack) {
OSKextLog(this,
kOSKextLogErrorLevel |
kOSKextLogDependenciesFlag,
@@ -9541,7 +7483,7 @@
getIdentifierCString());
goto finish;
}
- loopStack = localLoopStack.get();
+ localLoopStack = loopStack;
}
if (!loopStack->setObject(this)) {
OSKextLog(this,
@@ -9808,16 +7750,11 @@
for (i = 0; i < count; i++) {
OSKext * dependencyKext = OSDynamicCast(OSKext,
dependencies->getObject(i));
- dependencyKext->addBleedthroughDependencies(dependencies.get());
+ dependencyKext->addBleedthroughDependencies(dependencies);
}
}
#endif /* __LP64__ */
-#if CONFIG_KXLD
- /*
- * If we're not dynamically linking kexts, then we don't need to check
- * copyright strings. The linker in user space has already done this.
- */
if (hasPrivateKPIDependency) {
bool hasApplePrefix = false;
bool infoCopyrightIsValid = false;
@@ -9850,7 +7787,6 @@
goto finish;
}
}
-#endif // CONFIG_KXLD
result = true;
flags.hasAllDependencies = 1;
@@ -9877,6 +7813,9 @@
"Kext %s successfully resolved dependencies.",
getIdentifierCString());
}
+
+ OSSafeReleaseNULL(localLoopStack);
+ OSSafeReleaseNULL(libraryIterator);
return result;
}
@@ -9934,7 +7873,7 @@
kOSKextLogDependenciesFlag,
"Kext %s flushing dependencies.",
getIdentifierCString());
- dependencies.reset();
+ OSSafeReleaseNULL(dependencies);
}
if (!isKernelComponent()) {
flags.hasAllDependencies = 0;
@@ -9961,31 +7900,7 @@
OSArray *
OSKext::getDependencies(void)
{
- return dependencies.get();
-}
-
-bool
-OSKext::hasDependency(const OSSymbol * depID)
-{
- bool result __block;
-
- if (depID == getIdentifier()) {
- return true;
- }
- if (!dependencies) {
- return false;
- }
- result = false;
- dependencies->iterateObjects(^bool (OSObject * obj) {
- OSKext * kext;
- kext = OSDynamicCast(OSKext, obj);
- if (!kext) {
- return false;
- }
- result = (depID == kext->getIdentifier());
- return result;
- });
- return result;
+ return dependencies;
}
#if PRAGMA_MARK
@@ -10030,7 +7945,7 @@
}
if (!flags.autounloadEnabled) {
- const OSMetaClass * metaScan = NULL; // do not release
+ const OSMetaClass * metaScan = NULL;// do not release
for (metaScan = aClass; metaScan; metaScan = metaScan->getSuperClass()) {
if (metaScan == OSTypeID(IOService)) {
@@ -10041,7 +7956,7 @@
getIdentifierCString(),
aClass->getClassName());
- flags.autounloadEnabled = (0 == flags.unloadUnsupported);
+ flags.autounloadEnabled = 1;
break;
}
}
@@ -10117,7 +8032,7 @@
OSSet *
OSKext::getMetaClasses(void)
{
- return metaClasses.get();
+ return metaClasses;
}
/*********************************************************************
@@ -10126,14 +8041,14 @@
OSKext::hasOSMetaClassInstances(void)
{
bool result = false;
- OSSharedPtr<OSCollectionIterator> classIterator;
- OSMetaClass * checkClass = NULL; // do not release
+ OSCollectionIterator * classIterator = NULL; // must release
+ OSMetaClass * checkClass = NULL;// do not release
if (!metaClasses) {
goto finish;
}
- classIterator = OSCollectionIterator::withCollection(metaClasses.get());
+ classIterator = OSCollectionIterator::withCollection(metaClasses);
if (!classIterator) {
// xxx - log alloc failure?
goto finish;
@@ -10146,6 +8061,8 @@
}
finish:
+
+ OSSafeReleaseNULL(classIterator);
return result;
}
@@ -10157,7 +8074,7 @@
const char * kextIdentifier,
OSKextLogSpec msgLogSpec)
{
- OSSharedPtr<OSKext> theKext;
+ OSKext * theKext = NULL; // must release
theKext = OSKext::lookupKextWithIdentifier(kextIdentifier);
if (!theKext) {
@@ -10166,6 +8083,7 @@
theKext->reportOSMetaClassInstances(msgLogSpec);
finish:
+ OSSafeReleaseNULL(theKext);
return;
}
@@ -10174,14 +8092,14 @@
void
OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec)
{
- OSSharedPtr<OSCollectionIterator> classIterator;
- OSMetaClass * checkClass = NULL; // do not release
+ OSCollectionIterator * classIterator = NULL; // must release
+ OSMetaClass * checkClass = NULL;// do not release
if (!metaClasses) {
goto finish;
}
- classIterator = OSCollectionIterator::withCollection(metaClasses.get());
+ classIterator = OSCollectionIterator::withCollection(metaClasses);
if (!classIterator) {
goto finish;
}
@@ -10198,92 +8116,13 @@
}
finish:
+ OSSafeReleaseNULL(classIterator);
return;
}
#if PRAGMA_MARK
#pragma mark User-Space Requests
#endif
-
-static kern_return_t
-patchDextLaunchRequests(task_t calling_task, OSArray *requests)
-{
- OSReturn result = kOSReturnSuccess;
- for (uint32_t requestIndex = 0; requestIndex < requests->getCount(); requestIndex++) {
- OSDictionary * request = NULL; //do not release
- IOUserServerCheckInToken * token = NULL; //do not release
- OSString * requestPredicate = NULL; //do not release
- OSSharedPtr<OSNumber> portNameNumber;
- mach_port_name_t portName = 0;
- request = OSDynamicCast(OSDictionary, requests->getObject(requestIndex));
- if (!request) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
- "Elements of request should be of type OSDictionary");
- result = kOSKextReturnInternalError;
- goto finish;
- }
- requestPredicate = _OSKextGetRequestPredicate(request);
- if (!requestPredicate) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
- "Failed to get request predicate");
- result = kOSKextReturnInternalError;
- goto finish;
- }
- // is this a dext launch?
- if (requestPredicate->isEqualTo(kKextRequestPredicateRequestDaemonLaunch)) {
- token = OSDynamicCast(IOUserServerCheckInToken, _OSKextGetRequestArgument(request, kKextRequestArgumentCheckInToken));
- if (!token) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
- "Could not find a IOUserServerCheckInToken in daemon launch request.");
- result = kOSKextReturnInternalError;
- goto finish;
- }
- portName = iokit_make_send_right(calling_task, token, IKOT_IOKIT_IDENT);
- if (portName == 0 || portName == MACH_PORT_DEAD) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
- "Could not create send right for object.");
- result = kOSKextReturnInternalError;
- goto finish;
- }
- // Store the mach port name as a OSNumber
- portNameNumber = OSNumber::withNumber(portName, CHAR_BIT * sizeof(portName));
- if (!portNameNumber) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
- "Could not create OSNumber object.");
- result = kOSKextReturnNoMemory;
- goto finish;
- }
- if (!_OSKextSetRequestArgument(request, kKextRequestArgumentCheckInToken, portNameNumber.get())) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
- "Could not set OSNumber object as request " kKextRequestArgumentCheckInToken);
- result = kOSKextReturnNoMemory;
- goto finish;
- }
- }
-finish:
- if (result != kOSReturnSuccess) {
- break;
- }
- }
- return result;
-}
-
-bool
-OSKext::iokitDaemonActive()
-{
- bool result;
- IORecursiveLockLock(sKextLock);
- result = sIOKitDaemonActive && !sOSKextWasResetAfterUserspaceReboot;
- IORecursiveLockUnlock(sKextLock);
- return result;
-}
-
/*********************************************************************
* XXX - this function is a big ugly mess
*********************************************************************/
@@ -10302,28 +8141,24 @@
OSReturn result = kOSReturnError;
kern_return_t kmem_result = KERN_FAILURE;
- char * response = NULL; // returned by reference
+ char * response = NULL;// returned by reference
uint32_t responseLength = 0;
- bool taskCanManageAllKCs = false;
- bool taskOnlyManagesBootKC = false;
-
- OSSharedPtr<OSObject> parsedXML;
- OSDictionary * requestDict = NULL; // do not release
- OSSharedPtr<OSString> errorString;
-
- OSSharedPtr<OSObject> responseObject;
-
- OSSharedPtr<OSSerialize> serializer;
-
- OSSharedPtr<OSArray> logInfoArray;
-
- OSString * predicate = NULL; // do not release
- OSString * kextIdentifier = NULL; // do not release
- OSArray * kextIdentifiers = NULL; // do not release
- OSKext * theKext = NULL; // do not release
- OSBoolean * boolArg = NULL; // do not release
-
+ OSObject * parsedXML = NULL;// must release
+ OSDictionary * requestDict = NULL;// do not release
+ OSString * errorString = NULL;// must release
+
+ OSObject * responseObject = NULL;// must release
+
+ OSSerialize * serializer = NULL;// must release
+
+ OSArray * logInfoArray = NULL;// must release
+
+ OSString * predicate = NULL;// do not release
+ OSString * kextIdentifier = NULL;// do not release
+ OSArray * kextIdentifiers = NULL;// do not release
+ OSKext * theKext = NULL;// do not release
+ OSBoolean * boolArg = NULL;// do not release
IORecursiveLockLock(sKextLock);
@@ -10348,9 +8183,9 @@
result = kOSKextReturnBadData;
goto finish;
}
- parsedXML = OSUnserializeXML((const char *)requestBuffer, errorString);
+ parsedXML = OSUnserializeXML((const char *)requestBuffer, &errorString);
if (parsedXML) {
- requestDict = OSDynamicCast(OSDictionary, parsedXML.get());
+ requestDict = OSDynamicCast(OSDictionary, parsedXML);
}
if (!requestDict) {
const char * errorCString = "(unknown error)";
@@ -10378,74 +8213,27 @@
result = kOSKextReturnInvalidArgument;
goto finish;
}
+
OSKextLog(/* kext */ NULL,
kOSKextLogDebugLevel |
kOSKextLogIPCFlag,
"Received '%s' request from user space.",
predicate->getCStringNoCopy());
- /*
- * All management of file sets requires an entitlement
- */
result = kOSKextReturnNotPrivileged;
- if (predicate->isEqualTo(kKextRequestPredicateUnload) ||
- predicate->isEqualTo(kKextRequestPredicateStart) ||
- predicate->isEqualTo(kKextRequestPredicateStop) ||
- predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
- predicate->isEqualTo(kKextRequestPredicateSendResource) ||
- predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) ||
- predicate->isEqualTo(kKextRequestPredicateLoadCodeless) ||
- predicate->isEqualTo(kKextRequestPredicateLoadFromKC) ||
- predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) ||
- predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) ||
- predicate->isEqualTo(kKextRequestPredicateDaemonReady)) {
- if (!iokitDaemonAvailable()) {
- panic("Received unexpected request in environment where " kIOKitDaemonName " is unavailable");
- }
- if (hostPriv == HOST_PRIV_NULL) {
+ if (hostPriv == HOST_PRIV_NULL) {
+ /* must be root to use these kext requests */
+ if (predicate->isEqualTo(kKextRequestPredicateUnload) ||
+ predicate->isEqualTo(kKextRequestPredicateStart) ||
+ predicate->isEqualTo(kKextRequestPredicateStop) ||
+ predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
+ predicate->isEqualTo(kKextRequestPredicateSendResource)) {
OSKextLog(/* kext */ NULL,
kOSKextLogErrorLevel |
kOSKextLogIPCFlag,
"Access Failure - must be root user.");
goto finish;
}
- taskCanManageAllKCs = IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement) == TRUE;
- taskOnlyManagesBootKC = IOCurrentTaskHasEntitlement(kOSKextOnlyBootKCManagementEntitlement) == TRUE;
-
- if (!taskCanManageAllKCs && !taskOnlyManagesBootKC) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel |
- kOSKextLogIPCFlag,
- "Access Failure - client not entitled to manage file sets.");
- goto finish;
- }
-
- /*
- * The OnlyBootKC entitlement restricts the
- * collection-management entitlement to only managing kexts in
- * the BootKC. All other predicates that alter global state or
- * add new KCs are disallowed.
- */
- if (taskOnlyManagesBootKC &&
- (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
- predicate->isEqualTo(kKextRequestPredicateSendResource) ||
- predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) ||
- predicate->isEqualTo(kKextRequestPredicateLoadCodeless) ||
- predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) ||
- predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) ||
- predicate->isEqualTo(kKextRequestPredicateDaemonReady))) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel |
- kOSKextLogIPCFlag,
- "Access Failure - client not entitled to manage non-primary KCs");
- goto finish;
- }
-
- /*
- * If we get here, then the process either has the full KC
- * management entitlement, or it has the BootKC-only
- * entitlement and the request is about the BootKC.
- */
}
/* Get common args in anticipation of use.
@@ -10460,17 +8248,6 @@
boolArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
requestDict, kKextRequestArgumentValueKey));
- if (taskOnlyManagesBootKC &&
- theKext &&
- theKext->isInFileset() &&
- theKext->kc_type != KCKindPrimary) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel |
- kOSKextLogIPCFlag,
- "Access Failure - client not entitled to manage kext in non-primary KC");
- result = kOSKextReturnNotPrivileged;
- goto finish;
- }
result = kOSKextReturnInvalidArgument;
if (predicate->isEqualTo(kKextRequestPredicateStart)) {
@@ -10505,49 +8282,6 @@
} else {
result = theKext->stop();
}
- } else if (predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles)) {
- result = OSKext::setMissingAuxKCBundles(requestDict);
- } else if (predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable)) {
- if (!kextIdentifier) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel |
- kOSKextLogIPCFlag,
- "Invalid arguments to AuxKC Bundle Available request.");
- } else {
- result = OSKext::setAuxKCBundleAvailable(kextIdentifier, requestDict);
- }
- } else if (predicate->isEqualTo(kKextRequestPredicateLoadFromKC)) {
- if (!kextIdentifier) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel |
- kOSKextLogIPCFlag,
- "Invalid arguments to kext load from KC request.");
- } else if (!theKext) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel |
- kOSKextLogIPCFlag,
- "Kext %s not found for load from KC request.",
- kextIdentifier->getCStringNoCopy());
- result = kOSKextReturnNotFound;
- } else if (!theKext->isInFileset()) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel |
- kOSKextLogIPCFlag,
- "Kext %s does not exist in a KC: refusing to load.",
- kextIdentifier->getCStringNoCopy());
- result = kOSKextReturnNotLoadable;
- } else {
- result = OSKext::loadKextFromKC(theKext, requestDict);
- }
- } else if (predicate->isEqualTo(kKextRequestPredicateLoadCodeless)) {
- if (!kextIdentifier) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel |
- kOSKextLogIPCFlag,
- "Invalid arguments to codeless kext load interface (missing identifier).");
- } else {
- result = OSKext::loadCodelessKext(kextIdentifier, requestDict);
- }
} else if (predicate->isEqualTo(kKextRequestPredicateUnload)) {
if (!kextIdentifier) {
OSKextLog(/* kext */ NULL,
@@ -10562,14 +8296,10 @@
kextIdentifier->getCStringNoCopy());
result = kOSKextReturnNotFound;
} else {
- if (theKext->isDriverKit()) {
- result = OSKext::removeDext(theKext);
- } else {
- OSBoolean * terminateFlag = OSDynamicCast(OSBoolean,
- _OSKextGetRequestArgument(requestDict,
- kKextRequestArgumentTerminateIOServicesKey));
- result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue);
- }
+ OSBoolean * terminateFlag = OSDynamicCast(OSBoolean,
+ _OSKextGetRequestArgument(requestDict,
+ kKextRequestArgumentTerminateIOServicesKey));
+ result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue);
}
} else if (predicate->isEqualTo(kKextRequestPredicateSendResource)) {
result = OSKext::dispatchResource(requestDict);
@@ -10586,9 +8316,7 @@
goto finish;
}
} else if (predicate->isEqualTo(kKextRequestPredicateGetLoaded) ||
- predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID) ||
- predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection) ||
- predicate->isEqualTo(kKextRequestPredicateGetDexts)) {
+ predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) {
OSBoolean * delayAutounloadBool = NULL;
OSObject * infoKeysRaw = NULL;
OSArray * infoKeys = NULL;
@@ -10633,12 +8361,7 @@
responseObject = OSKext::copyLoadedKextInfo(kextIdentifiers, infoKeys);
} else if (predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) {
responseObject = OSKext::copyLoadedKextInfoByUUID(kextIdentifiers, infoKeys);
- } else if (predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection)) {
- responseObject = OSKext::copyKextCollectionInfo(requestDict, infoKeys);
- } else if (predicate->isEqualTo(kKextRequestPredicateGetDexts)) {
- responseObject = OSKext::copyDextsInfo(kextIdentifiers, infoKeys);
- }
-
+ }
if (!responseObject) {
result = kOSKextReturnInternalError;
} else {
@@ -10652,7 +8375,7 @@
/* Hand the current sKernelRequests array to the caller
* (who must release it), and make a new one.
*/
- responseObject = os::move(sKernelRequests);
+ responseObject = sKernelRequests;
sKernelRequests = OSArray::withCapacity(0);
sPostedKextLoadIdentifiers->flushCollection();
OSKextLog(/* kext */ NULL,
@@ -10663,21 +8386,12 @@
} else if (predicate->isEqualTo(kKextRequestPredicateGetAllLoadRequests)) {
/* Return the set of all requested bundle identifiers */
responseObject = sAllKextLoadIdentifiers;
+ responseObject->retain();
OSKextLog(/* kext */ NULL,
kOSKextLogDebugLevel |
kOSKextLogIPCFlag,
"Returning load requests.");
result = kOSReturnSuccess;
- } else if (predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC)) {
- printf("KextLog: Loading FileSet KC(s)\n");
- result = OSKext::loadFileSetKexts(requestDict);
- } else if (predicate->isEqualTo(kKextRequestPredicateDaemonReady)) {
- bool active = iokitDaemonActive();
- printf("KextLog: " kIOKitDaemonName " is %s\n", active ? "active" : "not active");
- if (sOSKextWasResetAfterUserspaceReboot) {
- printf("KextLog: was reset after userspace reboot\n");
- }
- result = active ? kOSReturnSuccess : kIOReturnNotReady;
} else {
OSKextLog(/* kext */ NULL,
kOSKextLogDebugLevel |
@@ -10709,31 +8423,8 @@
result = kOSKextReturnNoMemory;
goto finish;
}
- /*
- * Before serializing the kernel requests, patch the dext launch requests so
- * that the value for kKextRequestArgumentCheckInToken is a mach port name for the
- * IOUserServerCheckInToken kernel object.
- */
- if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
- OSArray * requests = OSDynamicCast(OSArray, responseObject.get());
- task_t calling_task = current_task();
- if (!requests) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
- "responseObject should be an OSArray if predicate is " kKextRequestPredicateGetKernelRequests);
- result = kOSKextReturnInternalError;
- goto finish;
- }
- result = patchDextLaunchRequests(calling_task, requests);
- if (result != kOSReturnSuccess) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
- "Failed to patch dext launch requests.");
- goto finish;
- }
- }
-
- if (!responseObject->serialize(serializer.get())) {
+
+ if (!responseObject->serialize(serializer)) {
OSKextLog(/* kext */ NULL,
kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
"Failed to serialize response to request from user space.");
@@ -10751,7 +8442,7 @@
/* This kmem_alloc sets the return value of the function.
*/
kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer,
- round_page(responseLength), KMA_DATA_SHARED, VM_KERN_MEMORY_OSKEXT);
+ round_page(responseLength), VM_KERN_MEMORY_OSKEXT);
if (kmem_result != KERN_SUCCESS) {
OSKextLog(/* kext */ NULL,
kOSKextLogErrorLevel |
@@ -10780,339 +8471,39 @@
logInfoArray = OSKext::clearUserSpaceLogFilter();
if (logInfoArray && logInfoOut && logInfoLengthOut) {
- (void)OSKext::serializeLogInfo(logInfoArray.get(),
+ (void)OSKext::serializeLogInfo(logInfoArray,
logInfoOut, logInfoLengthOut);
}
IORecursiveLockUnlock(sKextLock);
+ OSSafeReleaseNULL(parsedXML);
+ OSSafeReleaseNULL(errorString);
+ OSSafeReleaseNULL(responseObject);
+ OSSafeReleaseNULL(serializer);
+ OSSafeReleaseNULL(logInfoArray);
+
return result;
}
-#if PRAGMA_MARK
-#pragma mark Linked Kext Collection Support
-#endif
-
-static int
-__whereIsAddr(vm_offset_t theAddr, unsigned long *segSizes, vm_offset_t *segAddrs, int segCount)
-{
- for (int i = 0; i < segCount; i++) {
- vm_offset_t segStart = segAddrs[i];
- vm_offset_t segEnd = segStart + (vm_offset_t)segSizes[i];
-
- if (theAddr >= segStart && theAddr < segEnd) {
- return i;
- }
- }
- return -1;
-}
-
-static void
-__slideOldKaslrOffsets(kernel_mach_header_t *mh,
- kernel_segment_command_t *kextTextSeg,
- OSData *kaslrOffsets)
-{
- static const char *plk_segNames[] = {
- "__TEXT",
- "__TEXT_EXEC",
- "__DATA",
- "__DATA_CONST",
- "__LINKEDIT",
- "__PRELINK_TEXT",
- "__PLK_TEXT_EXEC",
- "__PRELINK_DATA",
- "__PLK_DATA_CONST",
- "__PLK_LLVM_COV",
- "__PLK_LINKEDIT",
- "__PRELINK_INFO"
- };
- static const size_t num_plk_seg = (size_t)(sizeof(plk_segNames) / sizeof(plk_segNames[0]));
-
- unsigned long plk_segSizes[num_plk_seg];
- vm_offset_t plk_segAddrs[num_plk_seg];
-
- for (size_t i = 0; i < num_plk_seg; i++) {
- plk_segSizes[i] = 0;
- plk_segAddrs[i] = (vm_offset_t)getsegdatafromheader(mh, plk_segNames[i], &plk_segSizes[i]);
- }
-
- uint64_t kextTextStart = (uint64_t)kextTextSeg->vmaddr;
-
- int slidKextAddrCount = 0;
- int badSlideAddr = 0;
- int badSlideTarget = 0;
-
- struct kaslrPackedOffsets {
- uint32_t count; /* number of offsets */
- uint32_t offsetsArray[]; /* offsets to slide */
- };
- const struct kaslrPackedOffsets *myOffsets = NULL;
- myOffsets = (const struct kaslrPackedOffsets *)kaslrOffsets->getBytesNoCopy();
-
- for (uint32_t j = 0; j < myOffsets->count; j++) {
- uint64_t slideOffset = (uint64_t)myOffsets->offsetsArray[j];
- vm_offset_t *slideAddr = (vm_offset_t *)((uint64_t)kextTextStart + slideOffset);
- int slideAddrSegIndex = -1;
- int addrToSlideSegIndex = -1;
-
- slideAddrSegIndex = __whereIsAddr((vm_offset_t)slideAddr, &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg);
- if (slideAddrSegIndex >= 0) {
- addrToSlideSegIndex = __whereIsAddr(ml_static_slide(*slideAddr), &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg);
- if (addrToSlideSegIndex < 0) {
- badSlideTarget++;
- continue;
- }
- } else {
- badSlideAddr++;
- continue;
- }
-
- slidKextAddrCount++;
- *slideAddr = ml_static_slide(*slideAddr);
- } // for ...
-}
-
-
-
-/********************************************************************
-* addKextsFromKextCollection
-*
-* Input: MachO header of kext collection. The MachO is assumed to
-* have a section named 'info_seg_name,info_sect_name' that
-* contains a serialized XML info dictionary. This dictionary
-* contains a UUID, possibly a set of relocations (for older
-* kxld-built binaries), and an array of kext personalities.
-*
-********************************************************************/
-bool
-OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh,
- OSDictionary *infoDict, const char *text_seg_name,
- OSData **kcUUID, kc_kind_t type)
-{
- bool result = false;
-
- OSArray *kextArray = NULL; // do not release
- OSData *infoDictKCUUID = NULL; // do not release
- OSData *kaslrOffsets = NULL; // do not release
-
- IORegistryEntry *registryRoot = NULL; // do not release
- OSSharedPtr<OSNumber> kcKextCount;
-
- /* extract the KC UUID from the dictionary */
- infoDictKCUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
- if (infoDictKCUUID) {
- if (infoDictKCUUID->getLength() != sizeof(uuid_t)) {
- panic("kcUUID length is %d, expected %lu",
- infoDictKCUUID->getLength(), sizeof(uuid_t));
- }
- }
-
- /* locate the array of kext dictionaries */
- kextArray = OSDynamicCast(OSArray, infoDict->getObject(kPrelinkInfoDictionaryKey));
- if (!kextArray) {
- OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
- "The given KC has no kext info dictionaries");
- goto finish;
- }
-
- /*
- * old-style KASLR offsets may be present in the info dictionary. If
- * we find them, use them and eventually slide them.
- */
- kaslrOffsets = OSDynamicCast(OSData, infoDict->getObject(kPrelinkLinkKASLROffsetsKey));
-
- /*
- * Before processing any kexts, locate the special kext bundle which
- * contains a list of kexts that we are to prevent from loading.
- */
- createExcludeListFromPrelinkInfo(kextArray);
-
- /*
- * Create OSKext objects for each kext we find in the array of kext
- * info plist dictionaries.
- */
- for (int i = 0; i < (int)kextArray->getCount(); ++i) {
- OSDictionary *kextDict = NULL;
- kextDict = OSDynamicCast(OSDictionary, kextArray->getObject(i));
- if (!kextDict) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel |
- kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
- "Kext info dictionary for kext #%d isn't a dictionary?", i);
- continue;
- }
-
- /*
- * Create the kext for the entry, then release it, because the
- * kext system keeps a reference around until the kext is
- * explicitly removed. Any creation/registration failures are
- * already logged for us.
- */
- withPrelinkedInfoDict(kextDict, (kaslrOffsets ? TRUE : FALSE), type);
- }
-
- /*
- * slide old-style kxld relocations
- * NOTE: this is still used on embedded KCs built with kcgen
- * TODO: Remove this once we use the new kext linker everywhere!
- */
- if (kaslrOffsets && vm_kernel_slide > 0) {
- kernel_segment_command_t *text_segment = NULL;
- text_segment = getsegbynamefromheader(mh, text_seg_name);
- if (!text_segment) {
- OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
- "Can't find a TEXT segment named '%s' in macho header", text_seg_name);
- goto finish;
- }
-
- __slideOldKaslrOffsets(mh, text_segment, kaslrOffsets);
- /* All kexts covered by the old-style kaslr relocation list are now slid, set VM protections for them */
- setAllVMAttributes();
- }
-
- /* Store the number of prelinked kexts in the registry so we can tell
- * when the system has been started from a prelinked kernel.
- */
- registryRoot = IORegistryEntry::getRegistryRoot();
- assert(registryRoot);
-
- kcKextCount = OSNumber::withNumber((unsigned long long)infoDict->getCount(), 8 * sizeof(uint32_t));
- assert(kcKextCount);
- if (kcKextCount) {
- OSSharedPtr<OSObject> prop = registryRoot->copyProperty(kOSPrelinkKextCountKey);
- OSNumber *num;
- num = OSDynamicCast(OSNumber, prop.get());
- if (num) {
- kcKextCount->addValue(num->unsigned64BitValue());
- }
- registryRoot->setProperty(kOSPrelinkKextCountKey, kcKextCount.get());
- }
-
- OSKextLog(/* kext */ NULL,
- kOSKextLogProgressLevel |
- kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag |
- kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
- "%u prelinked kexts", infoDict->getCount());
-
-
- if (kcUUID && infoDictKCUUID) {
- *kcUUID = OSData::withData(infoDictKCUUID).detach();
- }
-
- result = true;
-
-finish:
- return result;
-}
-
-bool
-OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh,
- OSDictionary *infoDict, const char *text_seg_name,
- OSSharedPtr<OSData> &kcUUID, kc_kind_t type)
-{
- OSData *result = NULL;
- bool success = addKextsFromKextCollection(mh,
- infoDict,
- text_seg_name,
- &result,
- type);
- if (success) {
- kcUUID.reset(result, OSNoRetain);
- }
- return success;
-}
-
-static OSSharedPtr<OSObject> deferredAuxKCXML;
-bool
-OSKext::registerDeferredKextCollection(kernel_mach_header_t *mh,
- OSSharedPtr<OSObject> &parsedXML, kc_kind_t type)
-{
- if (type != KCKindAuxiliary) {
- return false;
- }
-
- kernel_mach_header_t *_mh;
- _mh = (kernel_mach_header_t*)PE_get_kc_header(type);
- if (!_mh || _mh != mh) {
- return false;
- }
-
- if (deferredAuxKCXML) {
- /* only allow this to be called once */
- OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
- "An Aux KC has already been registered for deferred processing.");
- return false;
- }
-
- OSDictionary *infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
- if (!infoDict) {
- OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
- "The Aux KC has info dictionary");
- return false;
- }
-
- OSData *kcUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
- if (!kcUUID || kcUUID->getLength() != sizeof(uuid_t)) {
- OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
- "The Aux KC has no UUID in %s", kPrelinkInfoKCIDKey);
- return false;
- }
-
- /*
- * Copy the AuxKC UUID to make sure that the kern.auxiliaryfilesetuuid
- * sysctl can return the UUID to user space which will check this
- * value for errors.
- */
- memcpy((void *)&auxkc_uuid, (const void *)kcUUID->getBytesNoCopy(),
- kcUUID->getLength());
- uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string);
- auxkc_uuid_valid = TRUE;
-
- deferredAuxKCXML = parsedXML;
-
- return true;
-}
-
-OSSharedPtr<OSObject>
-OSKext::consumeDeferredKextCollection(kc_kind_t type)
-{
- if (type != KCKindAuxiliary || !deferredAuxKCXML) {
- return NULL;
- }
-
- return os::move(deferredAuxKCXML);
-}
-
-#if PRAGMA_MARK
-#pragma mark Profile-Guided-Optimization Support
-#endif
// #include <InstrProfiling.h>
extern "C" {
-uint64_t __llvm_profile_get_size_for_buffer_internal(
- const char *DataBegin,
- const char *DataEnd,
- const char *CountersBegin,
- const char *CountersEnd,
- const char *BitmapBegin,
- const char *BitmapEnd,
- const char *NamesBegin,
- const char *NamesEnd,
- const char *VTableBegin,
- const char *VTableEnd,
- const char *VNamesBegin,
- const char *VNamesEnd);
-int __llvm_profile_write_buffer_internal(
- char *Buffer,
- const char *DataBegin,
- const char *DataEnd,
- const char *CountersBegin,
- const char *CountersEnd,
- const char *BitmapBegin,
- const char *BitmapEnd,
- const char *NamesBegin,
- const char *NamesEnd);
-}
+uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin,
+ const char *DataEnd,
+ const char *CountersBegin,
+ const char *CountersEnd,
+ const char *NamesBegin,
+ const char *NamesEnd);
+int __llvm_profile_write_buffer_internal(char *Buffer,
+ const char *DataBegin,
+ const char *DataEnd,
+ const char *CountersBegin,
+ const char *CountersEnd,
+ const char *NamesBegin,
+ const char *NamesEnd);
+}
+
static
void
@@ -11172,12 +8563,13 @@
OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
"INSTANCE", instance_uuid_string);
- OSSharedPtr<OSData> uuid_data;
+ OSData *uuid_data;
uuid_t uuid;
uuid_string_t uuid_string;
uuid_data = kext->copyUUID();
if (uuid_data) {
memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
+ OSSafeReleaseNULL(uuid_data);
uuid_unparse(uuid, uuid_string);
OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
"UUID", uuid_string);
@@ -11228,7 +8620,6 @@
kernel_section_t *sect_prf_cnts = NULL;
uint64_t size;
size_t metadata_size = 0;
- size_t offset_to_pairs = 0;
sect_prf_data = kext->lookupSection("__DATA", "__llvm_prf_data");
sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_names");
@@ -11239,9 +8630,6 @@
}
sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
- // Ignore some sections used by optional PGO variants.
- const char *unused_section = NULL;
-
if (!sect_prf_data || !sect_prf_name || !sect_prf_cnts) {
err = ENOTSUP;
goto out;
@@ -11250,10 +8638,7 @@
size = __llvm_profile_get_size_for_buffer_internal(
(const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
(const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
- unused_section /* bits */, unused_section /* bits end */,
- (const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size,
- unused_section /* vtab */, unused_section /* vtab end */,
- unused_section /* vnam */, unused_section /* vnam end */);
+ (const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
if (metadata) {
metadata_size = OSKextPgoMetadataSize(kext);
@@ -11276,7 +8661,6 @@
pBuffer,
(const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
(const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
- unused_section /* bits */, unused_section /* bits end */,
(const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
if (err) {
@@ -11285,12 +8669,6 @@
}
if (metadata) {
- offset_to_pairs = sizeof(struct pgo_metadata_footer) + metadata_size;
- if (offset_to_pairs > UINT32_MAX) {
- err = E2BIG;
- goto out;
- }
-
char *end_of_buffer = pBuffer + size;
struct pgo_metadata_footer *footerp = (struct pgo_metadata_footer *) (end_of_buffer - sizeof(struct pgo_metadata_footer));
char *metadata_buffer = end_of_buffer - (sizeof(struct pgo_metadata_footer) + metadata_size);
@@ -11305,7 +8683,7 @@
struct pgo_metadata_footer footer;
footer.magic = htonl(0x6d657461);
footer.number_of_pairs = htonl( num_pairs );
- footer.offset_to_pairs = htonl((uint32_t)offset_to_pairs );
+ footer.offset_to_pairs = htonl( sizeof(struct pgo_metadata_footer) + metadata_size );
memcpy(footerp, &footer, sizeof(footer));
}
}
@@ -11324,7 +8702,7 @@
int metadata)
{
int err = 0;
- OSSharedPtr<OSKext> kext;
+ OSKext *kext = NULL;
IORecursiveLockLock(sKextLock);
@@ -11353,7 +8731,8 @@
prev->next = &s.list_head;
next->prev = &s.list_head;
- kext.reset();
+ kext->release();
+ kext = NULL;
IORecursiveLockSleep(sKextLock, &s, THREAD_ABORTSAFE);
@@ -11365,10 +8744,13 @@
err = s.err;
} else {
- err = OSKextGrabPgoDataLocked(kext.get(), metadata, kext->instance_uuid, pSize, pBuffer, bufferSize);
+ err = OSKextGrabPgoDataLocked(kext, metadata, kext->instance_uuid, pSize, pBuffer, bufferSize);
}
out:
+ if (kext) {
+ kext->release();
+ }
IORecursiveLockUnlock(sKextLock);
@@ -11405,18 +8787,18 @@
}
}
-OSSharedPtr<OSDictionary>
+OSDictionary *
OSKext::copyLoadedKextInfoByUUID(
OSArray * kextIdentifiers,
OSArray * infoKeys)
{
- OSSharedPtr<OSDictionary> result;
- OSSharedPtr<OSDictionary> kextInfo;
+ OSDictionary * result = NULL;
+ OSDictionary * kextInfo = NULL; // must release
uint32_t max_count, i, j;
uint32_t idCount = 0;
uint32_t idIndex = 0;
IORecursiveLockLock(sKextLock);
- OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
+ OSArray *list[2] = {sLoadedKexts, sLoadedDriverKitKexts};
uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
#if CONFIG_MACF
@@ -11461,11 +8843,11 @@
for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
for (i = 0; i < count[j]; i++) {
- OSKext *thisKext = NULL; // do not release
+ OSKext *thisKext = NULL;// do not release
Boolean includeThis = true;
uuid_t thisKextUUID;
uuid_t thisKextTextUUID;
- OSSharedPtr<OSData> uuid_data;
+ OSData *uuid_data;
uuid_string_t uuid_key;
thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
@@ -11479,6 +8861,7 @@
}
memcpy(&thisKextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextUUID));
+ OSSafeReleaseNULL(uuid_data);
uuid_unparse(thisKextUUID, uuid_key);
@@ -11487,6 +8870,7 @@
continue;
}
memcpy(&thisKextTextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextTextUUID));
+ OSSafeReleaseNULL(uuid_data);
/* Skip current kext if we have a list of UUIDs and
* it isn't in the list.
@@ -11521,7 +8905,8 @@
kextInfo = thisKext->copyInfo(infoKeys);
if (kextInfo) {
- result->setObject(uuid_key, kextInfo.get());
+ result->setObject(uuid_key, kextInfo);
+ kextInfo->release();
}
if (kextIdentifiers && !kextIdentifiers->getCount()) {
@@ -11539,358 +8924,12 @@
/*********************************************************************
*********************************************************************/
/* static */
-OSSharedPtr<OSDictionary>
-OSKext::copyKextCollectionInfo(
- OSDictionary *requestDict,
- OSArray *infoKeys)
-{
- OSSharedPtr<OSDictionary> result;
- OSString *collectionType = NULL;
- OSObject *rawLoadedState = NULL;
- OSString *loadedState = NULL;
-
- kc_kind_t kc_request_kind = KCKindUnknown;
- bool onlyLoaded = false;
- bool onlyUnloaded = false;
-
-#if CONFIG_MACF
- /* Is the calling process allowed to query kext info? */
- if (current_task() != kernel_task) {
- int macCheckResult = 0;
- kauth_cred_t cred = NULL;
-
- cred = kauth_cred_get_with_ref();
- macCheckResult = mac_kext_check_query(cred);
- kauth_cred_unref(&cred);
-
- if (macCheckResult != 0) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel | kOSKextLogLoadFlag,
- "Failed to query kext info (MAC policy error 0x%x).",
- macCheckResult);
- goto finish;
- }
- }
-#endif
-
- if (infoKeys && !infoKeys->getCount()) {
- infoKeys = NULL;
- }
-
- collectionType = OSDynamicCast(OSString,
- _OSKextGetRequestArgument(requestDict,
- kKextRequestArgumentCollectionTypeKey));
- if (!collectionType) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel |
- kOSKextLogIPCFlag,
- "Invalid '%s' argument to kext collection info request.",
- kKextRequestArgumentCollectionTypeKey);
- goto finish;
- }
- if (collectionType->isEqualTo(kKCTypePrimary)) {
- kc_request_kind = KCKindPrimary;
- } else if (collectionType->isEqualTo(kKCTypeSystem)) {
- kc_request_kind = KCKindPageable;
- } else if (collectionType->isEqualTo(kKCTypeAuxiliary)) {
- kc_request_kind = KCKindAuxiliary;
- } else if (collectionType->isEqualTo(kKCTypeCodeless)) {
- kc_request_kind = KCKindNone;
- } else if (!collectionType->isEqualTo(kKCTypeAny)) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel |
- kOSKextLogIPCFlag,
- "Invalid '%s' argument value '%s' to kext collection info request.",
- kKextRequestArgumentCollectionTypeKey,
- collectionType->getCStringNoCopy());
- goto finish;
- }
-
- rawLoadedState = _OSKextGetRequestArgument(requestDict,
- kKextRequestArgumentLoadedStateKey);
- if (rawLoadedState) {
- loadedState = OSDynamicCast(OSString, rawLoadedState);
- if (!loadedState) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel |
- kOSKextLogIPCFlag,
- "Invalid '%s' argument to kext collection info request.",
- kKextRequestArgumentLoadedStateKey);
- goto finish;
- }
- }
- if (loadedState) {
- if (loadedState->isEqualTo("Loaded")) {
- onlyLoaded = true;
- } else if (loadedState->isEqualTo("Unloaded")) {
- onlyUnloaded = true;
- } else if (!loadedState->isEqualTo("Any")) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel | kOSKextLogLoadFlag,
- "Invalid '%s' argument value '%s' for '%s' collection info",
- kKextRequestArgumentLoadedStateKey,
- loadedState->getCStringNoCopy(),
- collectionType->getCStringNoCopy());
- goto finish;
- }
- }
-
- result = OSDictionary::withCapacity(sKextsByID->getCount());
- if (!result) {
- goto finish;
- }
-
- IORecursiveLockLock(sKextLock);
- { // start block scope
- sKextsByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj)
- {
- OSKext *thisKext = NULL; // do not release
- OSSharedPtr<OSDictionary> kextInfo;
-
- (void)thisKextID;
-
- thisKext = OSDynamicCast(OSKext, obj);
- if (!thisKext) {
- return false;
- }
-
- /*
- * skip the kext if it came from the wrong collection type
- * (and the caller requested a specific type)
- */
- if ((kc_request_kind != KCKindUnknown) && (thisKext->kc_type != kc_request_kind)) {
- return false;
- }
-
- /*
- * respect the caller's desire to find only loaded or
- * unloaded kexts
- */
- if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
- return false;
- }
- if (onlyUnloaded && (-1U != sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
- return false;
- }
-
- kextInfo = thisKext->copyInfo(infoKeys);
- if (kextInfo) {
- result->setObject(thisKext->getIdentifier(), kextInfo.get());
- }
- return false;
- });
- } // end block scope
- IORecursiveLockUnlock(sKextLock);
-
-finish:
- return result;
-}
-
-/* static */
-OSSharedPtr<OSArray>
-OSKext::copyDextsInfo(
- OSArray *kextIdentifiers,
- OSArray *infoKeys)
-{
- OSSharedPtr<OSArray> result = NULL;
- uint32_t idCount = 0;
- bool getActive = false;
- bool getLoaded = false;
- bool getUnloaded = false;
- bool getPendingUpgrade = false;
- unsigned int avgDextCount = 0;
-
-#if CONFIG_MACF
- /* Is the calling process allowed to query dext info? */
- if (current_task() != kernel_task) {
- int macCheckResult = 0;
- kauth_cred_t cred = NULL;
-
- cred = kauth_cred_get_with_ref();
- macCheckResult = mac_kext_check_query(cred);
- kauth_cred_unref(&cred);
-
- if (macCheckResult != 0) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel | kOSKextLogLoadFlag,
- "Failed to query kext info (MAC policy error 0x%x).",
- macCheckResult);
- goto finish;
- }
- }
-#endif
- /*
- * No infoKeys means return everything we
- * know about the dexts.
- */
- if (infoKeys && !infoKeys->getCount()) {
- infoKeys = NULL;
- }
-
- /*
- * Empty list of bundle ids is equivalent to
- * no list (get all).
- */
- if (kextIdentifiers && !kextIdentifiers->getCount()) {
- kextIdentifiers = NULL;
- } else if (kextIdentifiers) {
- idCount = kextIdentifiers->getCount();
- }
-
- /*
- * Caller can specify which state of dexts to query.
- */
- if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveKey)) {
- getActive = true;
- }
- if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveLoadedKey)) {
- getLoaded = true;
- }
- if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveUnloadedKey)) {
- getUnloaded = true;
- }
- if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStatePendingUpgradeKey)) {
- getPendingUpgrade = true;
- }
-
- /*
- * By default we are going to return all active and pendingUpgrade dexts
- * only.
- */
- if (!(getActive || getLoaded || getUnloaded || getPendingUpgrade)) {
- getActive = true;
- getPendingUpgrade = true;
- }
-
- /*
- * We return a dictionary of dexts
- * for every group requested.
- */
- avgDextCount = sLoadedDriverKitKexts->getCount() + sDriverKitToUpgradeByID->getCount();
- result = OSArray::withCapacity(avgDextCount);
- if (!result) {
- goto finish;
- }
-
- IORecursiveLockLock(sKextLock);
- { // start block scope
- if (getActive || getLoaded || getUnloaded) {
- sKextsByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj)
- {
- OSKext *thisKext = NULL; // do not release
- OSSharedPtr<OSDictionary> kextInfo;
- Boolean includeThis = true;
- (void)thisKextID;
-
- thisKext = OSDynamicCast(OSKext, obj);
- if (!thisKext || !thisKext->isDriverKit()) {
- return false;
- }
-
- /*
- * Skip current dext if we have a list of bundle IDs and
- * it isn't in the list.
- */
- if (kextIdentifiers) {
- includeThis = false;
-
- for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
- const OSString * thisRequestID = OSDynamicCast(OSString,
- kextIdentifiers->getObject(idIndex));
- if (thisKextID->isEqualTo(thisRequestID)) {
- includeThis = true;
- break;
- }
- }
- }
-
- if (!includeThis) {
- return false;
- }
-
- OSSharedPtr<OSString> state;
- if (sLoadedDriverKitKexts->getNextIndexOfObject(thisKext, 0) == -1U) {
- if (!(getActive || getUnloaded)) {
- return false;
- }
- state = OSString::withCString(kOSBundleDextStateActiveUnloadedKey);
- } else {
- if (!(getActive || getLoaded)) {
- return false;
- }
- state = OSString::withCString(kOSBundleDextStateActiveLoadedKey);
- }
-
- kextInfo = thisKext->copyInfo(infoKeys);
- if (kextInfo) {
- kextInfo->setObject(kOSBundleDextStateKey, state.get());
- result->setObject(kextInfo.get());
- }
-
- return false;
- });
- }
-
- if (getPendingUpgrade) {
- sDriverKitToUpgradeByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj)
- {
- OSKext *thisKext = NULL; // do not release
- OSSharedPtr<OSDictionary> kextInfo;
- Boolean includeThis = true;
- (void)thisKextID;
-
- thisKext = OSDynamicCast(OSKext, obj);
- if (!thisKext) {
- return false;
- }
- __assert_only bool isDext = thisKext->isDriverKit();
- assert(isDext == true);
-
- /*
- * Skip current dext if we have a list of bundle IDs and
- * it isn't in the list.
- */
- if (kextIdentifiers) {
- includeThis = false;
-
- for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
- const OSString * thisRequestID = OSDynamicCast(OSString,
- kextIdentifiers->getObject(idIndex));
- if (thisKextID->isEqualTo(thisRequestID)) {
- includeThis = true;
- break;
- }
- }
- }
-
- if (!includeThis) {
- return false;
- }
-
- kextInfo = thisKext->copyInfo(infoKeys);
- if (kextInfo) {
- OSSharedPtr<OSString> state = OSString::withCString(kOSBundleDextStatePendingUpgradeKey);
- kextInfo->setObject(kOSBundleDextStateKey, state.get());
- result->setObject(kextInfo.get());
- }
- return false;
- });
- }
- } // end block scope
- IORecursiveLockUnlock(sKextLock);
-finish:
- return result;
-}
-
-/*********************************************************************
-*********************************************************************/
-/* static */
-OSSharedPtr<OSDictionary>
+OSDictionary *
OSKext::copyLoadedKextInfo(
OSArray * kextIdentifiers,
OSArray * infoKeys)
{
- OSSharedPtr<OSDictionary> result;
+ OSDictionary * result = NULL;
uint32_t idCount = 0;
bool onlyLoaded;
@@ -11974,51 +9013,51 @@
"kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n",
vm_slinkedit, vm_elinkedit);
#endif
- { // start block scope
- sKextsByID->iterateObjects(^bool (const OSSymbol * thisKextID, OSObject * obj)
- {
- OSKext * thisKext = NULL; // do not release
- Boolean includeThis = true;
- OSSharedPtr<OSDictionary> kextInfo;
-
- thisKext = OSDynamicCast(OSKext, obj);
- if (!thisKext) {
- return false;
- }
-
- /* Skip current kext if not yet started and caller didn't request all.
- */
- if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
- return false;
- }
-
- /* Skip current kext if we have a list of bundle IDs and
- * it isn't in the list.
- */
- if (kextIdentifiers) {
- includeThis = false;
-
- for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
- const OSString * thisRequestID = OSDynamicCast(OSString,
- kextIdentifiers->getObject(idIndex));
- if (thisKextID->isEqualTo(thisRequestID)) {
- includeThis = true;
- break;
- }
+
+ sKextsByID->iterateObjects(^bool (const OSSymbol * thisKextID, OSObject * obj)
+ {
+ OSKext * thisKext = NULL;// do not release
+ Boolean includeThis = true;
+ OSDictionary * kextInfo = NULL;// must release
+
+ thisKext = OSDynamicCast(OSKext, obj);
+ if (!thisKext) {
+ return false;;
+ }
+
+ /* Skip current kext if not yet started and caller didn't request all.
+ */
+ if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
+ return false;;
+ }
+
+ /* Skip current kext if we have a list of bundle IDs and
+ * it isn't in the list.
+ */
+ if (kextIdentifiers) {
+ includeThis = false;
+
+ for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
+ const OSString * thisRequestID = OSDynamicCast(OSString,
+ kextIdentifiers->getObject(idIndex));
+ if (thisKextID->isEqualTo(thisRequestID)) {
+ includeThis = true;
+ break;
}
}
-
- if (!includeThis) {
- return false;
- }
-
- kextInfo = thisKext->copyInfo(infoKeys);
- if (kextInfo) {
- result->setObject(thisKext->getIdentifier(), kextInfo.get());
- }
- return false;
- });
- } // end block scope
+ }
+
+ if (!includeThis) {
+ return false;
+ }
+
+ kextInfo = thisKext->copyInfo(infoKeys);
+ if (kextInfo) {
+ result->setObject(thisKext->getIdentifier(), kextInfo);
+ kextInfo->release();
+ }
+ return false;
+ });
finish:
IORecursiveLockUnlock(sKextLock);
@@ -12033,30 +9072,29 @@
*********************************************************************/
#define _OSKextLoadInfoDictCapacity (12)
-OSSharedPtr<OSDictionary>
+OSDictionary *
OSKext::copyInfo(OSArray * infoKeys)
{
- OSSharedPtr<OSDictionary> result;
- bool success = false;
- OSSharedPtr<OSData> headerData;
- OSSharedPtr<OSData> logData;
- OSSharedPtr<OSNumber> cpuTypeNumber;
- OSSharedPtr<OSNumber> cpuSubtypeNumber;
- OSString * versionString = NULL; // do not release
- OSString * bundleType = NULL; // do not release
- uint32_t executablePathCStringSize = 0;
- char * executablePathCString = NULL; // must kfree
- OSSharedPtr<OSString> executablePathString;
- OSSharedPtr<OSData> uuid;
- OSSharedPtr<OSArray> dependencyLoadTags;
- OSSharedPtr<OSCollectionIterator> metaClassIterator;
- OSSharedPtr<OSArray> metaClassInfo;
- OSSharedPtr<OSDictionary> metaClassDict;
- OSMetaClass * thisMetaClass = NULL; // do not release
- OSSharedPtr<OSString> metaClassName;
- OSSharedPtr<OSString> superclassName;
- kc_format_t kcformat;
- uint32_t count, i;
+ OSDictionary * result = NULL;
+ bool success = false;
+ OSData * headerData = NULL;// must release
+ OSData * logData = NULL;// must release
+ OSNumber * cpuTypeNumber = NULL;// must release
+ OSNumber * cpuSubtypeNumber = NULL;// must release
+ OSString * versionString = NULL;// do not release
+ uint32_t executablePathCStringSize = 0;
+ char * executablePathCString = NULL;// must release
+ OSString * executablePathString = NULL;// must release
+ OSData * uuid = NULL;// must release
+ OSNumber * scratchNumber = NULL;// must release
+ OSArray * dependencyLoadTags = NULL;// must release
+ OSCollectionIterator * metaClassIterator = NULL;// must release
+ OSArray * metaClassInfo = NULL;// must release
+ OSDictionary * metaClassDict = NULL;// must release
+ OSMetaClass * thisMetaClass = NULL;// do not release
+ OSString * metaClassName = NULL;// must release
+ OSString * superclassName = NULL;// must release
+ uint32_t count, i;
result = OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity);
if (!result) {
@@ -12068,10 +9106,6 @@
*/
if (infoKeys && !infoKeys->getCount()) {
infoKeys = NULL;
- }
-
- if (!PE_get_primary_kc_format(&kcformat)) {
- goto finish;
}
/* Headers, CPU type, and CPU subtype.
@@ -12085,8 +9119,8 @@
kernel_mach_header_t *kext_mach_hdr = (kernel_mach_header_t *)
linkedExecutable->getBytesNoCopy();
-#if !SECURE_KERNEL || XNU_TARGET_OS_OSX
- // do not return macho header info on shipping embedded - 19095897
+#if !SECURE_KERNEL
+ // do not return macho header info on shipping iOS - 19095897
if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey)) {
kernel_mach_header_t * temp_kext_mach_hdr;
struct load_command * lcp;
@@ -12105,7 +9139,7 @@
}
lcp = (struct load_command *) (temp_kext_mach_hdr + 1);
- for (i = 0; (i < temp_kext_mach_hdr->ncmds) && !flags.unslidMachO; i++) {
+ for (i = 0; i < temp_kext_mach_hdr->ncmds; i++) {
if (lcp->cmd == LC_SEGMENT_KERNEL) {
kernel_segment_command_t * segp;
kernel_section_t * secp;
@@ -12119,18 +9153,6 @@
segp->filesize = 0;
}
}
-
-#if __arm__ || __arm64__
- // iBoot disregards zero-size segments, just set their addresses to gVirtBase
- // and unslide them to avoid vm assertion failures / kernel logging breakage.
- if (segp->vmsize == 0 && segp->vmaddr < gVirtBase) {
- segp->vmaddr = gVirtBase;
- for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
- secp->size = 0; // paranoia :)
- secp->addr = gVirtBase;
- }
- }
-#endif
#if 0
OSKextLog(/* kext */ NULL,
@@ -12160,55 +9182,37 @@
}
lcp = (struct load_command *)((caddr_t)lcp + lcp->cmdsize);
}
- result->setObject(kOSBundleMachOHeadersKey, headerData.get());
+ result->setObject(kOSBundleMachOHeadersKey, headerData);
}
-#endif // !SECURE_KERNEL || XNU_TARGET_OS_OSX
+#endif // SECURE_KERNEL
if (_OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
osLogDataHeaderRef *header;
char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
- void *os_log_data = NULL;
- void *cstring_data = NULL;
- void *asan_cstring_data = NULL;
- unsigned long os_log_size = 0;
- unsigned long cstring_size = 0;
- unsigned long asan_cstring_size = 0;
- uint32_t os_log_offset = 0;
- uint32_t cstring_offset = 0;
- uint32_t asan_cstring_offset = 0;
+ void *os_log_data = NULL;
+ void *cstring_data = NULL;
+ unsigned long os_log_size = 0;
+ unsigned long cstring_size = 0;
+ uint32_t os_log_offset = 0;
+ uint32_t cstring_offset = 0;
bool res;
- os_log_data = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__os_log", &os_log_size);
- cstring_data = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__cstring", &cstring_size);
- asan_cstring_data = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__asan_cstring", &asan_cstring_size);
-
- /*
- * If the addresses in the Mach-O header are unslid, manually
- * slide them to allow for dereferencing.
- */
- if (flags.unslidMachO) {
- os_log_data = (os_log_data != nullptr) ? (void*)ml_static_slide((vm_offset_t)os_log_data) : nullptr;
- cstring_data = (cstring_data != nullptr) ? (void*)ml_static_slide((vm_offset_t)cstring_data) : nullptr;
- asan_cstring_data = (asan_cstring_data != nullptr) ? (void*)ml_static_slide((vm_offset_t)asan_cstring_data) : nullptr;
- }
-
- os_log_offset = (uintptr_t)os_log_data - (uintptr_t)kext_mach_hdr;
- cstring_offset = (uintptr_t)cstring_data - (uintptr_t)kext_mach_hdr;
- asan_cstring_offset = (uintptr_t)asan_cstring_data - (uintptr_t)kext_mach_hdr;
+ os_log_data = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__os_log", &os_log_size);
+ os_log_offset = getsectoffsetfromheader(kext_mach_hdr, "__TEXT", "__os_log");
+ cstring_data = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__cstring", &cstring_size);
+ cstring_offset = getsectoffsetfromheader(kext_mach_hdr, "__TEXT", "__cstring");
header = (osLogDataHeaderRef *) headerBytes;
header->version = OS_LOG_HDR_VERSION;
header->sect_count = NUM_OS_LOG_SECTIONS;
- header->sections[OS_LOG_SECT_IDX].sect_offset = os_log_offset;
- header->sections[OS_LOG_SECT_IDX].sect_size = (uint32_t) os_log_size;
- header->sections[CSTRING_SECT_IDX].sect_offset = cstring_offset;
- header->sections[CSTRING_SECT_IDX].sect_size = (uint32_t) cstring_size;
- header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = asan_cstring_offset;
- header->sections[ASAN_CSTRING_SECT_IDX].sect_size = (uint32_t) asan_cstring_size;
-
-
- logData = OSData::withValue(*header);
+ header->sections[OS_LOG_SECT_IDX].sect_offset = os_log_offset;
+ header->sections[OS_LOG_SECT_IDX].sect_size = (uint32_t) os_log_size;
+ header->sections[CSTRING_SECT_IDX].sect_offset = cstring_offset;
+ header->sections[CSTRING_SECT_IDX].sect_size = (uint32_t) cstring_size;
+
+
+ logData = OSData::withBytes(header, (u_int) (sizeof(osLogDataHeaderRef)));
if (!logData) {
goto finish;
}
@@ -12228,13 +9232,7 @@
goto finish;
}
}
- if (asan_cstring_data) {
- res = logData->appendBytes(asan_cstring_data, (u_int)header->sections[ASAN_CSTRING_SECT_IDX].sect_size);
- if (!res) {
- goto finish;
- }
- }
- result->setObject(kOSBundleLogStringsKey, logData.get());
+ result->setObject(kOSBundleLogStringsKey, logData);
}
if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey)) {
@@ -12244,7 +9242,7 @@
if (!cpuTypeNumber) {
goto finish;
}
- result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber.get());
+ result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber);
}
if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
@@ -12254,7 +9252,7 @@
if (!cpuSubtypeNumber) {
goto finish;
}
- result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber.get());
+ result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber);
}
} else {
if (isDriverKit() && _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
@@ -12265,14 +9263,12 @@
header = (osLogDataHeaderRef *) headerBytes;
header->version = OS_LOG_HDR_VERSION;
header->sect_count = NUM_OS_LOG_SECTIONS;
- header->sections[OS_LOG_SECT_IDX].sect_offset = 0;
- header->sections[OS_LOG_SECT_IDX].sect_size = (uint32_t) 0;
- header->sections[CSTRING_SECT_IDX].sect_offset = 0;
- header->sections[CSTRING_SECT_IDX].sect_size = (uint32_t) 0;
- header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = 0;
- header->sections[ASAN_CSTRING_SECT_IDX].sect_size = (uint32_t) 0;
-
- logData = OSData::withValue(*header);
+ header->sections[OS_LOG_SECT_IDX].sect_offset = 0;
+ header->sections[OS_LOG_SECT_IDX].sect_size = (uint32_t) 0;
+ header->sections[CSTRING_SECT_IDX].sect_offset = 0;
+ header->sections[CSTRING_SECT_IDX].sect_size = (uint32_t) 0;
+
+ logData = OSData::withBytes(header, (u_int) (sizeof(osLogDataHeaderRef)));
if (!logData) {
goto finish;
}
@@ -12280,27 +9276,14 @@
if (!res) {
goto finish;
}
- result->setObject(kOSBundleLogStringsKey, logData.get());
+ result->setObject(kOSBundleLogStringsKey, logData);
}
}
}
/* CFBundleIdentifier. We set this regardless because it's just stupid not to.
*/
- result->setObject(kCFBundleIdentifierKey, bundleID.get());
-
- /* kOSBundleDextUniqueIdentifierKey if present.
- */
- if (isDriverKit() && dextUniqueID != NULL) {
- result->setObject(kOSBundleDextUniqueIdentifierKey, dextUniqueID.get());
- }
-
- /* CFBundlePackageType
- */
- bundleType = infoDict ? OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey)): NULL;
- if (bundleType) {
- result->setObject(kCFBundlePackageTypeKey, bundleType);
- }
+ result->setObject(kCFBundleIdentifierKey, bundleID);
/* CFBundleVersion.
*/
@@ -12326,7 +9309,7 @@
*/
if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePathKey)) {
if (path) {
- result->setObject(kOSBundlePathKey, path.get());
+ result->setObject(kOSBundlePathKey, path);
}
}
@@ -12335,13 +9318,13 @@
*/
if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecutablePathKey)) {
if (path && executableRelPath) {
- uint32_t pathLength = path->getLength(); // gets incremented below
+ uint32_t pathLength = path->getLength(); // gets incremented below
// +1 for slash, +1 for \0
executablePathCStringSize = pathLength + executableRelPath->getLength() + 2;
- executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize,
- Z_WAITOK, VM_KERN_MEMORY_OSKEXT); // +1 for \0
+ executablePathCString = (char *)kalloc_tag((executablePathCStringSize) *
+ sizeof(char), VM_KERN_MEMORY_OSKEXT); // +1 for \0
if (!executablePathCString) {
goto finish;
}
@@ -12358,17 +9341,17 @@
goto finish;
}
- result->setObject(kOSBundleExecutablePathKey, executablePathString.get());
+ result->setObject(kOSBundleExecutablePathKey, executablePathString);
} else if (flags.builtin) {
- result->setObject(kOSBundleExecutablePathKey, bundleID.get());
+ result->setObject(kOSBundleExecutablePathKey, bundleID);
} else if (isDriverKit()) {
if (path) {
// +1 for slash, +1 for \0
uint32_t pathLength = path->getLength();
executablePathCStringSize = pathLength + 2;
- executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize,
- Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
+ executablePathCString = (char *)kalloc_tag((executablePathCStringSize) *
+ sizeof(char), VM_KERN_MEMORY_OSKEXT);
if (!executablePathCString) {
goto finish;
}
@@ -12382,7 +9365,7 @@
goto finish;
}
- result->setObject(kOSBundleExecutablePathKey, executablePathString.get());
+ result->setObject(kOSBundleExecutablePathKey, executablePathString);
}
}
}
@@ -12392,59 +9375,14 @@
if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) {
uuid = copyUUID();
if (uuid) {
- result->setObject(kOSBundleUUIDKey, uuid.get());
+ result->setObject(kOSBundleUUIDKey, uuid);
+ uuid->release();
}
}
if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleTextUUIDKey)) {
uuid = copyTextUUID();
if (uuid) {
- result->setObject(kOSBundleTextUUIDKey, uuid.get());
- }
- }
-
- /*
- * Info.plist digest
- */
- if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextInfoPlistDigestKey)) {
- OSData *digest;
- digest = infoDict ? OSDynamicCast(OSData, infoDict->getObject(kOSKextInfoPlistDigestKey)) : NULL;
- if (digest) {
- result->setObject(kOSKextInfoPlistDigestKey, digest);
- }
- }
-
- /*
- * Collection type
- */
- if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextBundleCollectionTypeKey)) {
- result->setObject(kOSKextBundleCollectionTypeKey, OSString::withCString(getKCTypeString()));
- }
-
- /*
- * Collection availability
- */
- if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextAuxKCAvailabilityKey)) {
- result->setObject(kOSKextAuxKCAvailabilityKey,
- isLoadable() ? kOSBooleanTrue : kOSBooleanFalse);
- }
-
- /*
- * Allows user load
- */
- if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleAllowUserLoadKey)) {
- OSBoolean *allowUserLoad = OSDynamicCast(OSBoolean, getPropertyForHostArch(kOSBundleAllowUserLoadKey));
- if (allowUserLoad) {
- result->setObject(kOSBundleAllowUserLoadKey, allowUserLoad);
- }
- }
-
- /*
- * Bundle Dependencies (OSBundleLibraries)
- */
- if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLibrariesKey)) {
- OSDictionary *libraries = OSDynamicCast(OSDictionary, getPropertyForHostArch(kOSBundleLibrariesKey));
- if (libraries) {
- result->setObject(kOSBundleLibrariesKey, libraries);
+ result->setObject(kOSBundleTextUUIDKey, uuid); uuid->release();
}
}
@@ -12474,12 +9412,13 @@
/* LoadTag (Index).
*/
if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadTagKey)) {
- OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber((unsigned long long)loadTag,
+ scratchNumber = OSNumber::withNumber((unsigned long long)loadTag,
/* numBits */ 8 * sizeof(loadTag));
if (!scratchNumber) {
goto finish;
}
- result->setObject(kOSBundleLoadTagKey, scratchNumber.get());
+ result->setObject(kOSBundleLoadTagKey, scratchNumber);
+ OSSafeReleaseNULL(scratchNumber);
}
/* LoadAddress, LoadSize.
@@ -12514,7 +9453,7 @@
if (flags.builtin) {
loadAddress = kmod_info->address;
- loadSize = (uint32_t)kmod_info->size;
+ loadSize = kmod_info->size;
} else {
loadAddress = (uint64_t)linkedExecutable->getBytesNoCopy();
loadSize = linkedExecutable->getLength();
@@ -12527,8 +9466,8 @@
*/
for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
if (seg->initprot & VM_PROT_EXECUTE) {
- execLoadAddress = (flags.unslidMachO) ? seg->vmaddr : ml_static_unslide(seg->vmaddr);
- execLoadSize = (uint32_t)seg->vmsize;
+ execLoadAddress = ml_static_unslide(seg->vmaddr);
+ execLoadSize = seg->vmsize;
break;
}
}
@@ -12537,7 +9476,7 @@
* from that. Otherwise it's the full load size.
*/
if (kmod_info) {
- wiredSize = loadSize - (uint32_t)kmod_info->hdr_size;
+ wiredSize = loadSize - kmod_info->hdr_size;
} else {
wiredSize = loadSize;
}
@@ -12553,71 +9492,71 @@
}
if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey)) {
- OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
+ scratchNumber = OSNumber::withNumber(
(unsigned long long)(loadAddress),
/* numBits */ 8 * sizeof(loadAddress));
if (!scratchNumber) {
goto finish;
}
- result->setObject(kOSBundleLoadAddressKey, scratchNumber.get());
+ result->setObject(kOSBundleLoadAddressKey, scratchNumber);
+ OSSafeReleaseNULL(scratchNumber);
}
- if (kcformat == KCFormatStatic || kcformat == KCFormatKCGEN) {
- if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCacheLoadAddressKey))
- && loadAddress && loadSize) {
- void *baseAddress = PE_get_kc_baseaddress(KCKindPrimary);
- if (!baseAddress) {
- goto finish;
- }
-
- OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
- (unsigned long long)ml_static_unslide((vm_offset_t)baseAddress),
- /* numBits */ 8 * sizeof(loadAddress));
- if (!scratchNumber) {
- goto finish;
- }
- result->setObject(kOSBundleCacheLoadAddressKey, scratchNumber.get());
+#if CONFIG_EMBEDDED
+ if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCacheLoadAddressKey))
+ && loadAddress && loadSize) {
+ scratchNumber = OSNumber::withNumber(
+ (unsigned long long)ml_static_unslide((uintptr_t)segLOWESTTEXT),
+ /* numBits */ 8 * sizeof(loadAddress));
+ if (!scratchNumber) {
+ goto finish;
}
- if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleKextsInKernelTextKey))
- && (this == sKernelKext) && gBuiltinKmodsCount) {
- result->setObject(kOSBundleKextsInKernelTextKey, kOSBooleanTrue);
- }
+ result->setObject(kOSBundleCacheLoadAddressKey, scratchNumber);
+ OSSafeReleaseNULL(scratchNumber);
}
-
+ if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleKextsInKernelTextKey))
+ && (this == sKernelKext) && gBuiltinKmodsCount) {
+ result->setObject(kOSBundleKextsInKernelTextKey, kOSBooleanTrue);
+ }
+#endif /* CONFIG_EMBEDDED */
if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey)) {
- OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
+ scratchNumber = OSNumber::withNumber(
(unsigned long long)(execLoadAddress),
/* numBits */ 8 * sizeof(execLoadAddress));
if (!scratchNumber) {
goto finish;
}
- result->setObject(kOSBundleExecLoadAddressKey, scratchNumber.get());
+ result->setObject(kOSBundleExecLoadAddressKey, scratchNumber);
+ OSSafeReleaseNULL(scratchNumber);
}
if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey)) {
- OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
+ scratchNumber = OSNumber::withNumber(
(unsigned long long)(loadSize),
/* numBits */ 8 * sizeof(loadSize));
if (!scratchNumber) {
goto finish;
}
- result->setObject(kOSBundleLoadSizeKey, scratchNumber.get());
+ result->setObject(kOSBundleLoadSizeKey, scratchNumber);
+ OSSafeReleaseNULL(scratchNumber);
}
if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey)) {
- OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
+ scratchNumber = OSNumber::withNumber(
(unsigned long long)(execLoadSize),
/* numBits */ 8 * sizeof(execLoadSize));
if (!scratchNumber) {
goto finish;
}
- result->setObject(kOSBundleExecLoadSizeKey, scratchNumber.get());
+ result->setObject(kOSBundleExecLoadSizeKey, scratchNumber);
+ OSSafeReleaseNULL(scratchNumber);
}
if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
- OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
+ scratchNumber = OSNumber::withNumber(
(unsigned long long)(wiredSize),
/* numBits */ 8 * sizeof(wiredSize));
if (!scratchNumber) {
goto finish;
}
- result->setObject(kOSBundleWiredSizeKey, scratchNumber.get());
+ result->setObject(kOSBundleWiredSizeKey, scratchNumber);
+ OSSafeReleaseNULL(scratchNumber);
}
}
}
@@ -12628,40 +9567,49 @@
if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleDependenciesKey)) {
if ((count = getNumDependencies())) {
dependencyLoadTags = OSArray::withCapacity(count);
- result->setObject(kOSBundleDependenciesKey, dependencyLoadTags.get());
+ result->setObject(kOSBundleDependenciesKey, dependencyLoadTags);
i = count - 1;
do {
OSKext * dependency = OSDynamicCast(OSKext,
dependencies->getObject(i));
+ OSSafeReleaseNULL(scratchNumber);
+
if (!dependency) {
continue;
}
- OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
+ scratchNumber = OSNumber::withNumber(
(unsigned long long)dependency->getLoadTag(),
/* numBits*/ 8 * sizeof(loadTag));
if (!scratchNumber) {
goto finish;
}
- dependencyLoadTags->setObject(scratchNumber.get());
+ dependencyLoadTags->setObject(scratchNumber);
} while (i--);
}
}
+
+ OSSafeReleaseNULL(scratchNumber);
/* OSBundleMetaClasses.
*/
if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleClassesKey)) {
if (metaClasses && metaClasses->getCount()) {
- metaClassIterator = OSCollectionIterator::withCollection(metaClasses.get());
+ metaClassIterator = OSCollectionIterator::withCollection(metaClasses);
metaClassInfo = OSArray::withCapacity(metaClasses->getCount());
if (!metaClassIterator || !metaClassInfo) {
goto finish;
}
- result->setObject(kOSBundleClassesKey, metaClassInfo.get());
+ result->setObject(kOSBundleClassesKey, metaClassInfo);
while ((thisMetaClass = OSDynamicCast(OSMetaClass,
metaClassIterator->getNextObject()))) {
+ OSSafeReleaseNULL(metaClassDict);
+ OSSafeReleaseNULL(scratchNumber);
+ OSSafeReleaseNULL(metaClassName);
+ OSSafeReleaseNULL(superclassName);
+
metaClassDict = OSDictionary::withCapacity(3);
if (!metaClassDict) {
goto finish;
@@ -12672,7 +9620,7 @@
superclassName = OSString::withCString(
thisMetaClass->getSuperClass()->getClassName());
}
- OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(),
+ scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(),
8 * sizeof(unsigned int));
/* Bail if any of the essentials is missing. The root class lacks a superclass,
@@ -12682,12 +9630,12 @@
goto finish;
}
- metaClassInfo->setObject(metaClassDict.get());
- metaClassDict->setObject(kOSMetaClassNameKey, metaClassName.get());
+ metaClassInfo->setObject(metaClassDict);
+ metaClassDict->setObject(kOSMetaClassNameKey, metaClassName);
if (superclassName) {
- metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName.get());
+ metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName);
}
- metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber.get());
+ metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber);
}
}
}
@@ -12695,16 +9643,17 @@
/* OSBundleRetainCount.
*/
if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleRetainCountKey)) {
+ OSSafeReleaseNULL(scratchNumber);
{
int kextRetainCount = getRetainCount() - 1;
if (isLoaded()) {
kextRetainCount--;
}
- OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
+ scratchNumber = OSNumber::withNumber(
(int)kextRetainCount,
/* numBits*/ 8 * sizeof(int));
if (scratchNumber) {
- result->setObject(kOSBundleRetainCountKey, scratchNumber.get());
+ result->setObject(kOSBundleRetainCountKey, scratchNumber);
}
}
}
@@ -12712,11 +9661,23 @@
success = true;
finish:
+ OSSafeReleaseNULL(headerData);
+ OSSafeReleaseNULL(logData);
+ OSSafeReleaseNULL(cpuTypeNumber);
+ OSSafeReleaseNULL(cpuSubtypeNumber);
+ OSSafeReleaseNULL(executablePathString);
if (executablePathCString) {
- kfree_data(executablePathCString, executablePathCStringSize);
- }
+ kfree(executablePathCString, executablePathCStringSize);
+ }
+ OSSafeReleaseNULL(scratchNumber);
+ OSSafeReleaseNULL(dependencyLoadTags);
+ OSSafeReleaseNULL(metaClassIterator);
+ OSSafeReleaseNULL(metaClassInfo);
+ OSSafeReleaseNULL(metaClassDict);
+ OSSafeReleaseNULL(metaClassName);
+ OSSafeReleaseNULL(superclassName);
if (!success) {
- result.reset();
+ OSSafeReleaseNULL(result);
}
return result;
}
@@ -12728,19 +9689,24 @@
OSKext::copyUserExecutablePath(const OSSymbol * bundleID, char * pathResult, size_t pathSize)
{
bool ok;
- OSSharedPtr<OSKext> kext;
+ OSKext * kext;
IORecursiveLockLock(sKextLock);
- kext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(bundleID)), OSRetain);
+ kext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID));
+ if (kext) {
+ kext->retain();
+ }
IORecursiveLockUnlock(sKextLock);
if (!kext || !kext->path || !kext->userExecutableRelPath) {
+ OSSafeReleaseNULL(kext);
return false;
}
snprintf(pathResult, pathSize, "%s/Contents/MacOS/%s",
kext->path->getCStringNoCopy(),
kext->userExecutableRelPath->getCStringNoCopy());
ok = true;
+ kext->release();
return ok;
}
@@ -12756,19 +9722,20 @@
void * context,
OSKextRequestTag * requestTagOut)
{
- OSReturn result = kOSReturnError;
- OSSharedPtr<OSKext> callbackKext; // looked up
+ OSReturn result = kOSReturnError;
+ OSKext * callbackKext = NULL;// must release (looked up)
OSKextRequestTag requestTag = -1;
- OSSharedPtr<OSNumber> requestTagNum;
- OSSharedPtr<OSDictionary> requestDict;
- OSSharedPtr<OSString> kextIdentifier;
- OSSharedPtr<OSString> resourceName;
-
- OSSharedPtr<OSDictionary> callbackRecord;
- OSSharedPtr<OSValueObject<OSKextRequestResourceCallback> > callbackWrapper;
-
- OSSharedPtr<OSValueObject<void *> > contextWrapper;
+ OSNumber * requestTagNum = NULL;// must release
+
+ OSDictionary * requestDict = NULL;// must release
+ OSString * kextIdentifier = NULL;// must release
+ OSString * resourceName = NULL;// must release
+
+ OSDictionary * callbackRecord = NULL;// must release
+ OSData * callbackWrapper = NULL;// must release
+
+ OSData * contextWrapper = NULL;// must release
IORecursiveLockLock(sKextLock);
@@ -12828,7 +9795,7 @@
requestTag = sNextRequestTag++;
result = _OSKextCreateRequest(kKextRequestPredicateRequestResource,
- requestDict);
+ &requestDict);
if (result != kOSReturnSuccess) {
goto finish;
}
@@ -12840,35 +9807,35 @@
if (!kextIdentifier ||
!resourceName ||
!requestTagNum ||
- !_OSKextSetRequestArgument(requestDict.get(),
- kKextRequestArgumentBundleIdentifierKey, kextIdentifier.get()) ||
- !_OSKextSetRequestArgument(requestDict.get(),
- kKextRequestArgumentNameKey, resourceName.get()) ||
- !_OSKextSetRequestArgument(requestDict.get(),
- kKextRequestArgumentRequestTagKey, requestTagNum.get())) {
+ !_OSKextSetRequestArgument(requestDict,
+ kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
+ !_OSKextSetRequestArgument(requestDict,
+ kKextRequestArgumentNameKey, resourceName) ||
+ !_OSKextSetRequestArgument(requestDict,
+ kKextRequestArgumentRequestTagKey, requestTagNum)) {
result = kOSKextReturnNoMemory;
goto finish;
}
- callbackRecord = OSDynamicPtrCast<OSDictionary>(requestDict->copyCollection());
+ callbackRecord = OSDynamicCast(OSDictionary, requestDict->copyCollection());
if (!callbackRecord) {
result = kOSKextReturnNoMemory;
goto finish;
}
// we validate callback address at call time
- callbackWrapper = OSValueObjectWithValue(callback);
+ callbackWrapper = OSData::withBytes((void *)&callback, sizeof(void *));
if (context) {
- contextWrapper = OSValueObjectWithValue(context);
- }
- if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord.get(),
- kKextRequestArgumentCallbackKey, callbackWrapper.get())) {
+ contextWrapper = OSData::withBytes((void *)&context, sizeof(void *));
+ }
+ if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord,
+ kKextRequestArgumentCallbackKey, callbackWrapper)) {
result = kOSKextReturnNoMemory;
goto finish;
}
if (context) {
- if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord.get(),
- kKextRequestArgumentContextKey, contextWrapper.get())) {
+ if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord,
+ kKextRequestArgumentContextKey, contextWrapper)) {
result = kOSKextReturnNoMemory;
goto finish;
}
@@ -12877,13 +9844,13 @@
/* Only post the requests after all the other potential failure points
* have been passed.
*/
- if (!sKernelRequests->setObject(requestDict.get()) ||
- !sRequestCallbackRecords->setObject(callbackRecord.get())) {
+ if (!sKernelRequests->setObject(requestDict) ||
+ !sRequestCallbackRecords->setObject(callbackRecord)) {
result = kOSKextReturnNoMemory;
goto finish;
}
- OSKext::pingIOKitDaemon();
+ OSKext::pingKextd();
result = kOSReturnSuccess;
if (requestTagOut) {
@@ -12898,11 +9865,11 @@
if (result != kOSReturnSuccess) {
unsigned int index;
- index = sKernelRequests->getNextIndexOfObject(requestDict.get(), 0);
+ index = sKernelRequests->getNextIndexOfObject(requestDict, 0);
if (index != (unsigned int)-1) {
sKernelRequests->removeObject(index);
}
- index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord.get(), 0);
+ index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord, 0);
if (index != (unsigned int)-1) {
sRequestCallbackRecords->removeObject(index);
}
@@ -12911,6 +9878,33 @@
OSKext::considerUnloads(/* rescheduleOnly? */ true);
IORecursiveLockUnlock(sKextLock);
+
+ if (callbackKext) {
+ callbackKext->release();
+ }
+ if (requestTagNum) {
+ requestTagNum->release();
+ }
+
+ if (requestDict) {
+ requestDict->release();
+ }
+ if (kextIdentifier) {
+ kextIdentifier->release();
+ }
+ if (resourceName) {
+ resourceName->release();
+ }
+
+ if (callbackRecord) {
+ callbackRecord->release();
+ }
+ if (callbackWrapper) {
+ callbackWrapper->release();
+ }
+ if (contextWrapper) {
+ contextWrapper->release();
+ }
return result;
}
@@ -12919,25 +9913,14 @@
OSKext::requestDaemonLaunch(
OSString *kextIdentifier,
OSString *serverName,
- OSNumber *serverTag,
- OSBoolean *reslide,
- IOUserServerCheckInToken * checkInToken,
- OSData *serverDUI)
+ OSNumber *serverTag)
{
OSReturn result = kOSReturnError;
- OSSharedPtr<OSDictionary> requestDict;
- unsigned int size = 0;
- const char *dextUniqueIDCString = NULL;
-
- if (!kextIdentifier || !serverName || !serverTag || !checkInToken) {
- return kOSKextReturnInvalidArgument;
- }
- if (!iokitDaemonAvailable()) {
- panic("Received unexpected request in environment where " kIOKitDaemonName " is unavailable");
- }
-
- if (serverDUI != NULL) {
- dextUniqueIDCString = getDextUniqueIDCString(serverDUI, &size);
+ OSDictionary * requestDict = NULL; // must release
+
+ if (!kextIdentifier || !serverName || !serverTag) {
+ result = kOSKextReturnInvalidArgument;
+ goto finish;
}
IORecursiveLockLock(sKextLock);
@@ -12945,109 +9928,41 @@
OSKextLog(/* kext */ NULL,
kOSKextLogDebugLevel |
kOSKextLogGeneralFlag,
- "Requesting daemon launch for %s %s with serverName %s and tag %llu%s",
+ "Requesting daemon launch for %s with serverName %s and tag %llu",
kextIdentifier->getCStringNoCopy(),
- (dextUniqueIDCString != NULL)?dextUniqueIDCString:"",
serverName->getCStringNoCopy(),
- serverTag->unsigned64BitValue(),
- reslide == kOSBooleanTrue ? " with reslid shared cache" : ""
+ serverTag->unsigned64BitValue()
);
- result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonLaunch, requestDict);
+ result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonLaunch, &requestDict);
if (result != kOSReturnSuccess) {
goto finish;
}
- if (!_OSKextSetRequestArgument(requestDict.get(),
+ if (!_OSKextSetRequestArgument(requestDict,
kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
- !_OSKextSetRequestArgument(requestDict.get(),
+ !_OSKextSetRequestArgument(requestDict,
kKextRequestArgumentDriverExtensionServerName, serverName) ||
- !_OSKextSetRequestArgument(requestDict.get(),
- kKextRequestArgumentDriverExtensionServerTag, serverTag) ||
- !_OSKextSetRequestArgument(requestDict.get(),
- kKextRequestArgumentDriverExtensionReslideSharedCache, reslide) ||
- !_OSKextSetRequestArgument(requestDict.get(),
- kKextRequestArgumentCheckInToken, checkInToken)) {
+ !_OSKextSetRequestArgument(requestDict,
+ kKextRequestArgumentDriverExtensionServerTag, serverTag)) {
result = kOSKextReturnNoMemory;
goto finish;
- }
-
- if (serverDUI) {
- if (!_OSKextSetRequestArgument(requestDict.get(),
- kOSBundleDextUniqueIdentifierKey, serverDUI)) {
- result = kOSKextReturnNoMemory;
- goto finish;
- }
}
/* Only post the requests after all the other potential failure points
* have been passed.
*/
- if (!sKernelRequests->setObject(requestDict.get())) {
+ if (!sKernelRequests->setObject(requestDict)) {
result = kOSKextReturnNoMemory;
goto finish;
}
- result = OSKext::pingIOKitDaemon();
- if (result != kOSReturnSuccess) {
- goto finish;
- }
+ OSKext::pingKextd();
result = kOSReturnSuccess;
finish:
IORecursiveLockUnlock(sKextLock);
- if (dextUniqueIDCString) {
- kfree_data(dextUniqueIDCString, size);
- }
- return result;
-}
-
-OSReturn
-OSKext::notifyDextUpgrade(
- OSString *kextIdentifier,
- OSData *dextUniqueIdentifier)
-{
- OSReturn result = kOSReturnError;
- OSSharedPtr<OSDictionary> requestDict;
- unsigned int size = 0;
- const char *dextUniqueIDCString = getDextUniqueIDCString(dextUniqueIdentifier, &size);
- assert(dextUniqueIDCString != NULL);
-
- IORecursiveLockLock(sKextLock);
-
- OSKextLog(NULL,
- kOSKextLogDebugLevel |
- kOSKextLogGeneralFlag,
- "Notifying of dext upgrade for %s with UniqueID %s",
- kextIdentifier->getCStringNoCopy(), dextUniqueIDCString);
-
- result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonUpgradeNotification, requestDict);
- if (result != kOSReturnSuccess) {
- goto finish;
- }
-
- if (!_OSKextSetRequestArgument(requestDict.get(),
- kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
- !_OSKextSetRequestArgument(requestDict.get(),
- kKextRequestArgumentDriverUniqueIdentifier, dextUniqueIdentifier)) {
- result = kOSKextReturnNoMemory;
- goto finish;
- }
-
- /* Only post the requests after all the other potential failure points
- * have been passed.
- */
- if (!sKernelRequests->setObject(requestDict.get())) {
- result = kOSKextReturnNoMemory;
- goto finish;
- }
- OSKext::pingIOKitDaemon();
-
- result = kOSReturnSuccess;
-finish:
- IORecursiveLockUnlock(sKextLock);
-
- if (dextUniqueIDCString != NULL) {
- kfree_data(dextUniqueIDCString, size);
+ if (requestDict) {
+ requestDict->release();
}
return result;
}
@@ -13059,27 +9974,10 @@
OSReturn
OSKext::dequeueCallbackForRequestTag(
OSKextRequestTag requestTag,
- OSSharedPtr<OSDictionary> &callbackRecordOut)
-{
- OSDictionary * callbackRecordOutRaw = NULL;
- OSReturn result;
-
- result = dequeueCallbackForRequestTag(requestTag,
- &callbackRecordOutRaw);
-
- if (kOSReturnSuccess == result) {
- callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain);
- }
-
- return result;
-}
-OSReturn
-OSKext::dequeueCallbackForRequestTag(
- OSKextRequestTag requestTag,
OSDictionary ** callbackRecordOut)
{
OSReturn result = kOSReturnError;
- OSSharedPtr<OSNumber> requestTagNum;
+ OSNumber * requestTagNum = NULL;// must release
requestTagNum = OSNumber::withNumber((long long unsigned int)requestTag,
8 * sizeof(requestTag));
@@ -13087,10 +9985,12 @@
goto finish;
}
- result = OSKext::dequeueCallbackForRequestTag(requestTagNum.get(),
+ result = OSKext::dequeueCallbackForRequestTag(requestTagNum,
callbackRecordOut);
finish:
+ OSSafeReleaseNULL(requestTagNum);
+
return result;
}
@@ -13101,28 +10001,11 @@
OSReturn
OSKext::dequeueCallbackForRequestTag(
OSNumber * requestTagNum,
- OSSharedPtr<OSDictionary> &callbackRecordOut)
-{
- OSDictionary * callbackRecordOutRaw = NULL;
- OSReturn result;
-
- result = dequeueCallbackForRequestTag(requestTagNum,
- &callbackRecordOutRaw);
-
- if (kOSReturnSuccess == result) {
- callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain);
- }
-
- return result;
-}
-OSReturn
-OSKext::dequeueCallbackForRequestTag(
- OSNumber * requestTagNum,
OSDictionary ** callbackRecordOut)
{
OSReturn result = kOSKextReturnInvalidArgument;
- OSDictionary * callbackRecord = NULL; // retain if matched!
- OSNumber * callbackTagNum = NULL; // do not release
+ OSDictionary * callbackRecord = NULL;// retain if matched!
+ OSNumber * callbackTagNum = NULL;// do not release
unsigned int count, i;
result = kOSReturnError;
@@ -13168,1150 +10051,9 @@
*********************************************************************/
/* static */
bool
-OSKext::pendingIOKitDaemonRequests(void)
+OSKext::isWaitingKextd(void)
{
return sRequestCallbackRecords && sRequestCallbackRecords->getCount();
-}
-
-/*********************************************************************
-* Acquires and releases sKextLock
-*
-* This function is designed to be called by kernelmanagerd and driverkitd
-* and it gathers all codeless kext and dext personalities, and then attempts
-* to map a System (pageable) KC and an Auxiliary (aux) KC.
-*
-* The pageable and aux KC can be loaded only once at boot time.
-* Even if the pageable or aux KC fail to load - this function will
-* not allow a new pageable or aux KC to be installed by subsequent calls.
-* This is done to avoid security issues where userspace has been compromised
-* or the pageable kc has been tampered with and the attacker
-* attempts to re-load a malicious variant.
-* However dexts can be dynamically loaded, so this function can be used
-* to request the installation of a new set of dexts even after boot time.
-*
-*
-*
-* Return: if a KC fails to load the return value will contain:
-* kOSKextReturnKCLoadFailure. If the pageable KC fails,
-* the return value will contain kOSKextReturnKCLoadFailureSystemKC.
-* Similarly, if the aux kc load fails, the return value will
-* contain kOSKextReturnKCLoadFailureAuxKC. The two values
-* compose with each other and with kOSKextReturnKCLoadFailure.
-*********************************************************************/
-/* static */
-OSReturn
-OSKext::loadFileSetKexts(OSDictionary * requestDict __unused)
-{
- static bool daemon_ready = false;
-
- OSReturn ret = kOSKextReturnInvalidArgument;
- OSReturn kcerr = 0;
- bool start_matching = false;
-
- bool allow_fileset_load = !daemon_ready;
-#if !(defined(__x86_64__) || defined(__i386__))
- /* never allow KCs full of kexts on non-x86 machines */
- allow_fileset_load = false;
-#endif
-
- /*
- * Change with 70582300
- */
-#if 0 || !defined(VM_MAPPED_KEXTS)
- /*
- * On platforms that don't support the SystemKC or a file-backed
- * AuxKC, the kext receipt for 3rd party kexts loaded by the booter
- * needs to be queried before we load any codeless kexts or release
- * any 3rd party kexts to run. On platforms that support a file-backed
- * AuxKC, this process is done via the kext audit mechanism.
- */
-
- printf("KextLog: waiting for kext receipt to be queried.\n");
- while (!IOServiceWaitForMatchingResource(kOSKextReceiptQueried, UINT64_MAX)) {
- IOSleep(30);
- }
-#endif /* !VM_MAPPED_KEXTS */
-
- /*
- * Get the args from the request. Right now we need the file
- * name for the pageable and the aux kext collection file sets.
- */
- OSDictionary * requestArgs = NULL; // do not release
- OSString * pageable_filepath = NULL; // do not release
- OSString * aux_filepath = NULL; // do not release
- OSArray * codeless_kexts = NULL; // do not release
-
- kernel_mach_header_t *akc_mh = NULL;
-
- requestArgs = OSDynamicCast(OSDictionary,
- requestDict->getObject(kKextRequestArgumentsKey));
-
- if (requestArgs == NULL) {
- OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
- "KextLog: No arguments in plist for loading fileset kext\n");
- printf("KextLog: No arguments in plist for loading fileset kext\n");
- return ret;
- }
-
- ret = kOSKextReturnDisabled;
-
- IORecursiveLockLock(sKextLock);
-
- if (!sLoadEnabled) {
- OSKextLog(NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag,
- "KextLog: Kext loading is disabled (attempt to load KCs).");
- IORecursiveLockUnlock(sKextLock);
- return ret;
- }
-
- pageable_filepath = OSDynamicCast(OSString,
- requestArgs->getObject(kKextRequestArgumentPageableKCFilename));
-
- if (allow_fileset_load && pageable_filepath != NULL) {
- printf("KextLog: Loading Pageable KC from file %s\n", pageable_filepath->getCStringNoCopy());
-
- ret = OSKext::loadKCFileSet(pageable_filepath->getCStringNoCopy(), KCKindPageable);
- if (ret) {
- OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
- "KextLog: loadKCFileSet for Pageable KC returned %d\n", ret);
-
- printf("KextLog: loadKCFileSet for Pageable KC returned %d\n", ret);
- ret = kOSKextReturnKCLoadFailure;
- kcerr |= kOSKextReturnKCLoadFailureSystemKC;
- goto try_auxkc;
- }
- /*
- * Even if the AuxKC fails to load, we still want to send
- * the System KC personalities to the catalog for matching
- */
- start_matching = true;
- } else if (pageable_filepath != NULL) {
- OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
- "KextLog: ignoring Pageable KC load from %s\n", pageable_filepath->getCStringNoCopy());
- ret = kOSKextReturnUnsupported;
- }
-
-try_auxkc:
- akc_mh = (kernel_mach_header_t*)PE_get_kc_header(KCKindAuxiliary);
- if (akc_mh) {
- /*
- * If we try to load a deferred AuxKC, then don't ever attempt
- * a filesystem map of a file
- */
- allow_fileset_load = false;
-
- /*
- * This function is only called once per boot, so we haven't
- * yet loaded an AuxKC. If we have registered the AuxKC mach
- * header, that means that the kext collection has been placed
- * in memory for us by the booter, and is waiting for us to
- * process it. Grab the deferred XML plist of info
- * dictionaries and add all the kexts.
- */
- OSSharedPtr<OSObject> parsedXML;
- OSSharedPtr<OSData> loaded_kcUUID;
- OSDictionary *infoDict;
- parsedXML = consumeDeferredKextCollection(KCKindAuxiliary);
- infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
-#if !defined(VM_MAPPED_KEXTS)
- /*
- * On platforms where we don't dynamically wire-down / page-in
- * kext memory, we need to maintain the invariant that if the
- * AuxKC in memory does not contain a kext receipt, then we
- * should not load any of the kexts.
- */
- size_t receipt_sz = 0;
- if (getsectdatafromheader(akc_mh, kReceiptInfoSegment, kAuxKCReceiptSection, &receipt_sz) == NULL || receipt_sz == 0) {
- OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
- "KextLog: WARNING: Failed to load AuxKC from memory: missing receipt");
- ret = kOSKextReturnKCLoadFailure;
- goto try_codeless;
- }
-#endif
- if (infoDict) {
- bool added;
- printf("KextLog: Adding kexts from in-memory AuxKC\n");
- added = OSKext::addKextsFromKextCollection(akc_mh, infoDict,
- kPrelinkTextSegment, loaded_kcUUID, KCKindAuxiliary);
- if (!loaded_kcUUID) {
- OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
- "KextLog: WARNING: did not find UUID in deferred Aux KC!");
- } else if (!added) {
- OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
- "KextLog: WARNING: Failed to load AuxKC from memory.");
- }
- /* only return success if the pageable load (above) was successful */
- if (ret != kOSKextReturnKCLoadFailure) {
- ret = kOSReturnSuccess;
- }
- /* the registration of the AuxKC parsed out the KC's UUID already */
- } else {
- if (daemon_ready) {
- /*
- * Complain, but don't return an error if this isn't the first time the
- * IOKit daemon is checking in. If the daemon ever restarts, we will
- * hit this case because we've already consumed the deferred personalities.
- * We return success here so that a call to this function from a restarted
- * daemon with no codeless kexts will succeed.
- */
- OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
- "KextLog: can't re-parse deferred AuxKC personalities on IOKit daemon restart");
- if (ret != kOSKextReturnKCLoadFailure) {
- ret = kOSReturnSuccess;
- }
- } else {
- /* this is a real error case */
- OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag,
- "KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary");
- printf("KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary\n");
- ret = kOSKextReturnKCLoadFailure;
- kcerr |= kOSKextReturnKCLoadFailureAuxKC;
- }
- }
- }
-
- aux_filepath = OSDynamicCast(OSString,
- requestArgs->getObject(kKextRequestArgumentAuxKCFilename));
- if (allow_fileset_load && aux_filepath != NULL) {
- printf("KextLog: Loading Aux KC from file %s\n", aux_filepath->getCStringNoCopy());
-
- ret = OSKext::loadKCFileSet(aux_filepath->getCStringNoCopy(), KCKindAuxiliary);
- if (ret) {
- OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
- "KextLog: loadKCFileSet for Aux KC returned %d\n", ret);
-
- printf("KextLog: loadKCFileSet for Aux KC returned %d\n", ret);
- ret = kOSKextReturnKCLoadFailure;
- kcerr |= kOSKextReturnKCLoadFailureAuxKC;
- goto try_codeless;
- }
- start_matching = true;
- } else if (aux_filepath != NULL) {
- OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
- "KextLog: Ignoring AuxKC load from %s\n", aux_filepath->getCStringNoCopy());
- if (ret != kOSKextReturnKCLoadFailure) {
- ret = kOSKextReturnUnsupported;
- }
- }
-
-try_codeless:
- /*
- * Load codeless kexts last so that there is no possibilty of a
- * codeless kext bundle ID preventing a kext in the system KC from
- * loading
- */
- codeless_kexts = OSDynamicCast(OSArray,
- requestArgs->getObject(kKextRequestArgumentCodelessPersonalities));
- if (codeless_kexts != NULL) {
- uint32_t count = codeless_kexts->getCount();
- OSKextLog(NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
- "KextLog: loading %d codeless kexts/dexts", count);
- for (uint32_t i = 0; i < count; i++) {
- OSDictionary *infoDict;
- infoDict = OSDynamicCast(OSDictionary,
- codeless_kexts->getObject(i));
- if (!infoDict) {
- continue;
- }
- // instantiate a new kext, and don't hold a reference
- // (the kext subsystem will hold one implicitly)
- OSKext::withCodelessInfo(infoDict, NULL);
- }
- /* ignore errors that are not KC load failures */
- if (ret != kOSKextReturnKCLoadFailure) {
- ret = kOSReturnSuccess;
- }
- start_matching = true;
- }
-
- /* send personalities to the IOCatalog once */
- if (ret == kOSReturnSuccess || start_matching || sOSKextWasResetAfterUserspaceReboot) {
- OSKext::sendAllKextPersonalitiesToCatalog(true);
- /*
- * This request necessarily came from the IOKit daemon (kernelmanagerd), so mark
- * things as active and start all the delayed matching: the
- * dext and codeless kext personalities should have all been
- * delivered via this one call.
- */
- if (!daemon_ready) {
- OSKext::setIOKitDaemonActive();
- OSKext::setDeferredLoadSucceeded(TRUE);
- IOService::iokitDaemonLaunched();
- }
- if (sOSKextWasResetAfterUserspaceReboot) {
- sOSKextWasResetAfterUserspaceReboot = false;
- OSKext::setIOKitDaemonActive();
- IOService::startDeferredMatches();
- }
- }
-
- if (ret == kOSKextReturnKCLoadFailure) {
- ret |= kcerr;
- }
-
- /*
- * Only allow this function to attempt to load the pageable and
- * aux KCs once per boot.
- */
- daemon_ready = true;
-
- IORecursiveLockUnlock(sKextLock);
-
- return ret;
-}
-
-OSReturn
-OSKext::resetMutableSegments(void)
-{
- kernel_segment_command_t *seg = NULL;
- kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address;
- u_int index = 0;
- OSKextSavedMutableSegment *savedSegment = NULL;
- uintptr_t kext_slide = PE_get_kc_slide(kc_type);
- OSReturn err;
-
- if (!savedMutableSegments) {
- OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag,
- "Kext %s cannot be reset, mutable segments were not saved.", getIdentifierCString());
- err = kOSKextReturnInternalError;
- goto finish;
- }
-
- for (seg = firstsegfromheader(k_mh), index = 0; seg; seg = nextsegfromheader(k_mh, seg)) {
- if (!segmentIsMutable(seg)) {
- continue;
- }
- uint64_t unslid_vmaddr = seg->vmaddr - kext_slide;
- uint64_t vmsize = seg->vmsize;
- err = kOSKextReturnInternalError;
- for (index = 0; index < savedMutableSegments->getCount(); index++) {
- savedSegment = OSDynamicCast(OSKextSavedMutableSegment, savedMutableSegments->getObject(index));
- assert(savedSegment);
- if (savedSegment->getVMAddr() == seg->vmaddr && savedSegment->getVMSize() == seg->vmsize) {
- OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag,
- "Resetting kext %s, mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1);
- err = savedSegment->restoreContents(seg);
- if (err != kOSReturnSuccess) {
- panic("Kext %s cannot be reset, mutable segment %llx->%llx could not be restored.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
- }
- }
- }
- if (err != kOSReturnSuccess) {
- panic("Kext %s cannot be reset, could not find saved mutable segment for %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
- }
- }
- err = kOSReturnSuccess;
-finish:
- return err;
-}
-
-
-/*********************************************************************
-* Assumes sKextLock is held.
-*********************************************************************/
-/* static */
-OSReturn
-OSKext::loadKCFileSet(
- const char *filepath,
- kc_kind_t type)
-{
-#if VM_MAPPED_KEXTS
- /* we only need to load filesets on systems that support VM_MAPPED kexts */
- OSReturn err;
- struct vnode *vp = NULL;
- void *fileset_control;
- off_t fsize;
- bool pageable = (type == KCKindPageable);
-
- if ((pageable && pageableKCloaded) ||
- (!pageable && auxKCloaded)) {
- OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
- "KC FileSet of type %s is already loaded", (pageable ? "Pageable" : "Aux"));
-
- return kOSKextReturnInvalidArgument;
- }
-
- /* Do not allow AuxKC to load if Pageable KC is not loaded */
- if (!pageable && !pageableKCloaded) {
- OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
- "Trying to load the Aux KC without loading the Pageable KC");
- return kOSKextReturnInvalidArgument;
- }
-
- fileset_control = ubc_getobject_from_filename(filepath, &vp, &fsize);
-
- if (fileset_control == NULL) {
- printf("Could not get memory control object for file %s", filepath);
-
- OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
- "Could not get memory control object for file %s", filepath);
- return kOSKextReturnInvalidArgument;
- }
- if (vp == NULL) {
- OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
- "Could not find vnode for file %s", filepath);
- return kOSKextReturnInvalidArgument;
- }
-
- kernel_mach_header_t *mh = NULL;
- uintptr_t slide = 0;
-
-#if CONFIG_CSR
- /*
- * When SIP is enabled, the KC we map must be SIP-protected
- */
- if (csr_check(CSR_ALLOW_UNRESTRICTED_FS) != 0) {
- struct vnode_attr va;
- int error;
- VATTR_INIT(&va);
- VATTR_WANTED(&va, va_flags);
- error = vnode_getattr(vp, &va, vfs_context_current());
- if (error) {
- OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
- "vnode_getattr(%s) failed (error=%d)", filepath, error);
- err = kOSKextReturnInternalError;
- goto finish;
- }
- if (!(va.va_flags & SF_RESTRICTED)) {
- OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
- "Path to KC '%s' is not SIP-protected", filepath);
- err = kOSKextReturnInvalidArgument;
- goto finish;
- }
- }
-#endif
-
- err = OSKext::mapKCFileSet(fileset_control, (vm_size_t)fsize, &mh, 0, &slide, pageable, NULL);
- if (err) {
- printf("KextLog: mapKCFileSet returned %d\n", err);
-
- OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
- "mapKCFileSet returned %d\n", err);
-
- err = kOSKextReturnInvalidArgument;
- }
-
-#if CONFIG_CSR
-finish:
-#endif
- /* Drop the vnode ref returned by ubc_getobject_from_filename if mapKCFileSet failed */
- assert(vp != NULL);
- if (err == kOSReturnSuccess) {
- PE_set_kc_vp(type, vp);
- if (pageable) {
- pageableKCloaded = true;
- } else {
- auxKCloaded = true;
- }
- } else {
- vnode_put(vp);
- }
-
- return err;
-#else
- (void)filepath;
- (void)type;
- return kOSKextReturnUnsupported;
-#endif // VM_MAPPED_KEXTS
-}
-
-#if defined(__x86_64__) || defined(__i386__)
-/*********************************************************************
-* Assumes sKextLock is held.
-*********************************************************************/
-/* static */
-OSReturn
-OSKext::mapKCFileSet(
- void *control,
- vm_size_t fsize,
- kernel_mach_header_t **mhp,
- off_t file_offset,
- uintptr_t *slidep,
- bool pageable,
- void *map_entry_list)
-{
- bool fileset_load = false;
- kern_return_t ret;
- OSReturn err;
- kernel_section_t *infoPlistSection = NULL;
- OSDictionary *infoDict = NULL;
-
- OSSharedPtr<OSObject> parsedXML;
- OSSharedPtr<OSString> errorString;
- OSSharedPtr<OSData> loaded_kcUUID;
-
- /* Check if initial load for file set */
- if (*mhp == NULL) {
- fileset_load = true;
-
- /* Get a page aligned address from kext map to map the file */
- vm_map_offset_t pagealigned_addr = get_address_from_kext_map(fsize);
- if (pagealigned_addr == 0) {
- return kOSKextReturnNoMemory;
- }
-
- *mhp = (kernel_mach_header_t *)pagealigned_addr;
-
- /* Allocate memory for bailout mechanism */
- map_entry_list = allocate_kcfileset_map_entry_list();
- if (map_entry_list == NULL) {
- return kOSKextReturnNoMemory;
- }
- }
-
- uintptr_t *slideptr = fileset_load ? slidep : NULL;
- err = mapKCTextSegment(control, mhp, file_offset, slideptr, map_entry_list);
- /* mhp and slideptr are updated by mapKCTextSegment */
- if (err) {
- if (fileset_load) {
- deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
- }
- return err;
- }
-
- /* Initialize the kc header globals */
- if (fileset_load) {
- if (pageable) {
- PE_set_kc_header(KCKindPageable, *mhp, *slidep);
- } else {
- PE_set_kc_header(KCKindAuxiliary, *mhp, *slidep);
- }
- }
-
- /* Iterate through all the segments and map necessary segments */
- struct load_command *lcp = (struct load_command *) (*mhp + 1);
- for (unsigned int i = 0; i < (*mhp)->ncmds; i++, lcp = (struct load_command *)((uintptr_t)lcp + lcp->cmdsize)) {
- vm_map_offset_t start;
- kernel_mach_header_t *k_mh = NULL;
- kernel_segment_command_t * seg = NULL;
- struct fileset_entry_command *fse = NULL;
-
- if (lcp->cmd == LC_SEGMENT_KERNEL) {
- seg = (kernel_segment_command_t *)lcp;
- start = ((uintptr_t)(seg->vmaddr)) + *slidep;
- } else if (lcp->cmd == LC_FILESET_ENTRY) {
- fse = (struct fileset_entry_command *)lcp;
- k_mh = (kernel_mach_header_t *)(((uintptr_t)(fse->vmaddr)) + *slidep);
-
- /* Map the segments of the mach-o binary */
- err = OSKext::mapKCFileSet(control, 0, &k_mh, fse->fileoff, slidep, pageable, map_entry_list);
- if (err) {
- deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
- return kOSKextReturnInvalidArgument;
- }
- continue;
- } else if (lcp->cmd == LC_DYLD_CHAINED_FIXUPS) {
- /* Check if the Aux KC is built pageable style */
- if (!pageable && !fileset_load && !auxKCloaded) {
- resetAuxKCSegmentOnUnload = true;
- }
- continue;
- } else {
- continue;
- }
-
- if (fileset_load) {
- if (seg->vmsize == 0) {
- continue;
- }
-
- /* Only map __PRELINK_INFO, __BRANCH_STUBS, __BRANCH_GOTS and __LINKEDIT sections */
- if (strncmp(seg->segname, kPrelinkInfoSegment, sizeof(seg->segname)) != 0 &&
- strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) != 0 &&
- strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) != 0 &&
- strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0) {
- continue;
- }
- } else {
- if (seg->vmsize == 0) {
- continue;
- }
-
- /* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */
- if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 ||
- strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 ||
- strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) {
- continue;
- }
- }
-
- ret = vm_map_kcfileset_segment(
- &start, seg->vmsize,
- (memory_object_control_t)control, seg->fileoff, seg->maxprot);
-
- if (ret != KERN_SUCCESS) {
- if (fileset_load) {
- deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
- }
- return kOSKextReturnInvalidArgument;
- }
- add_kcfileset_map_entry(map_entry_list, start, seg->vmsize);
- }
-
- /* Return if regular mach-o */
- if (!fileset_load) {
- return 0;
- }
-
- /*
- * Fixup for the Pageable KC and the Aux KC is done by
- * i386_slide_kext_collection_mh_addrs, but it differs in
- * following ways:
- *
- * PageableKC: Fixup only __BRANCH_STUBS segment and top level load commands.
- * The fixup of kext segments and kext load commands are done at kext
- * load time by calling i386_slide_individual_kext.
- *
- * AuxKC old style: Fixup all the segments and all the load commands.
- *
- * AuxKC pageable style: Same as the Pageable KC.
- */
- bool adjust_mach_header = (pageable ? true : ((resetAuxKCSegmentOnUnload) ? true : false));
- ret = i386_slide_kext_collection_mh_addrs(*mhp, *slidep, adjust_mach_header);
- if (ret != KERN_SUCCESS) {
- deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
- return kOSKextReturnInvalidArgument;
- }
-
- /* Get the prelink info dictionary */
- infoPlistSection = getsectbynamefromheader(*mhp, kPrelinkInfoSegment, kPrelinkInfoSection);
- parsedXML = OSUnserializeXML((const char *)infoPlistSection->addr, errorString);
- if (parsedXML) {
- infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
- }
-
- if (!infoDict) {
- const char *errorCString = "(unknown error)";
-
- if (errorString && errorString->getCStringNoCopy()) {
- errorCString = errorString->getCStringNoCopy();
- } else if (parsedXML) {
- errorCString = "not a dictionary";
- }
- OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
- "Error unserializing kext info plist section: %s.", errorCString);
- deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
- return kOSKextReturnInvalidArgument;
- }
-
- /* Validate that the Kext Collection is prelinked to the loaded KC */
- err = OSKext::validateKCFileSetUUID(infoDict, pageable ? KCKindPageable : KCKindAuxiliary);
- if (err) {
- deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
- return kOSKextReturnInvalidArgument;
- }
-
- /* Set Protection of Segments */
- OSKext::protectKCFileSet(*mhp, pageable ? KCKindPageable : KCKindAuxiliary);
-
- OSKext::addKextsFromKextCollection(*mhp,
- infoDict, kPrelinkTextSegment,
- loaded_kcUUID, pageable ? KCKindPageable : KCKindAuxiliary);
-
- /* Copy in the KC UUID */
- if (!loaded_kcUUID) {
- OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
- "WARNING: did not find UUID in prelinked %s KC!", pageable ? "Pageable" : "Aux");
- } else if (pageable) {
- pageablekc_uuid_valid = TRUE;
- memcpy((void *)&pageablekc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
- uuid_unparse_upper(pageablekc_uuid, pageablekc_uuid_string);
- } else {
- auxkc_uuid_valid = TRUE;
- memcpy((void *)&auxkc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
- uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string);
- }
-
- deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, FALSE, pageable);
-
- return 0;
-}
-
-/*********************************************************************
-* Assumes sKextLock is held.
-*********************************************************************/
-/* static */
-OSReturn
-OSKext::mapKCTextSegment(
- void *control,
- kernel_mach_header_t **mhp,
- off_t file_offset,
- uintptr_t *slidep,
- void *map_entry_list)
-{
- kern_return_t ret;
- vm_map_offset_t mach_header_map_size = vm_map_round_page(sizeof(kernel_mach_header_t),
- PAGE_MASK);
- vm_map_offset_t load_command_map_size = 0;
- kernel_mach_header_t *base_mh = *mhp;
-
- /* Map the mach header at start of fileset for now (vmaddr = 0) */
- ret = vm_map_kcfileset_segment(
- (vm_map_offset_t *)&base_mh, mach_header_map_size,
- (memory_object_control_t)control, file_offset, (VM_PROT_READ | VM_PROT_WRITE));
-
- if (ret != KERN_SUCCESS) {
- printf("Kext Log: mapKCTextSegment failed to map mach header of fileset %x", ret);
-
- OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
- "Failed to map mach header of kc fileset with error %d", ret);
- return kOSKextReturnInvalidArgument;
- }
-
- if (slidep) {
- /* Verify that it's an MH_FILESET */
- if (base_mh->filetype != MH_FILESET) {
- printf("Kext Log: mapKCTextSegment mach header filetype"
- " is not an MH_FILESET, it is %x", base_mh->filetype);
-
- OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
- "mapKCTextSegment mach header filetype is not an MH_FILESET, it is %x", base_mh->filetype);
-
- /* Unmap the mach header */
- vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
- return kOSKextReturnInvalidArgument;
- }
- }
-
- /* Map the remaining pages of load commands */
- if (base_mh->sizeofcmds > mach_header_map_size) {
- vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size;
- load_command_map_size = base_mh->sizeofcmds - mach_header_map_size;
-
- /* Map the load commands */
- ret = vm_map_kcfileset_segment(
- &load_command_addr, load_command_map_size,
- (memory_object_control_t)control, file_offset + mach_header_map_size,
- (VM_PROT_READ | VM_PROT_WRITE));
-
- if (ret != KERN_SUCCESS) {
- printf("KextLog: mapKCTextSegment failed to map load commands of fileset %x", ret);
- OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
- "Failed to map load commands of kc fileset with error %d", ret);
-
- /* Unmap the mach header */
- vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
- return kOSKextReturnInvalidArgument;
- }
- }
-
- kernel_segment_command_t *text_seg;
- text_seg = getsegbynamefromheader((kernel_mach_header_t *)base_mh, SEG_TEXT);
-
- /* Calculate the slide and vm addr of mach header */
- if (slidep) {
- *mhp = (kernel_mach_header_t *)((uintptr_t)base_mh + text_seg->vmaddr);
- *slidep = ((uintptr_t)*mhp) - text_seg->vmaddr;
- }
-
- /* Cache the text segment size and file offset before unmapping */
- vm_map_offset_t text_segment_size = text_seg->vmsize;
- vm_object_offset_t text_segment_fileoff = text_seg->fileoff;
- vm_prot_t text_maxprot = text_seg->maxprot;
-
- /* Unmap the first page and loadcommands and map the text segment */
- ret = vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
- assert(ret == KERN_SUCCESS);
-
- if (load_command_map_size) {
- vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size;
- ret = vm_unmap_kcfileset_segment(&load_command_addr, load_command_map_size);
- assert(ret == KERN_SUCCESS);
- }
-
- /* Map the text segment at actual vm addr specified in fileset */
- ret = vm_map_kcfileset_segment((vm_map_offset_t *)mhp, text_segment_size,
- (memory_object_control_t)control, text_segment_fileoff, text_maxprot);
- if (ret != KERN_SUCCESS) {
- OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
- "Failed to map Text segment of kc fileset with error %d", ret);
- return kOSKextReturnInvalidArgument;
- }
-
- add_kcfileset_map_entry(map_entry_list, (vm_map_offset_t)*mhp, text_segment_size);
- return 0;
-}
-
-/*********************************************************************
-* Assumes sKextLock is held.
-*********************************************************************/
-/* static */
-OSReturn
-OSKext::protectKCFileSet(
- kernel_mach_header_t *mh,
- kc_kind_t type)
-{
- vm_map_t kext_map = g_kext_map;
- kernel_segment_command_t * seg = NULL;
- vm_map_offset_t start = 0;
- vm_map_offset_t end = 0;
- vm_map_size_t size = 0;
- OSReturn ret = 0;
-
- /* Set VM permissions */
- seg = firstsegfromheader((kernel_mach_header_t *)mh);
- while (seg) {
- start = round_page(seg->vmaddr);
- end = trunc_page(seg->vmaddr + seg->vmsize);
- size = end - start;
-
- /*
- * Wire down and protect __TEXT, __BRANCH_STUBS and __BRANCH_GOTS
- * for the Pageable KC and the Aux KC, wire down and protect __LINKEDIT
- * for the Aux KC as well.
- */
- if (strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) == 0 ||
- strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) == 0 ||
- strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0 ||
- (type == KCKindAuxiliary && !resetAuxKCSegmentOnUnload &&
- strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0)) {
- ret = OSKext_protect((kernel_mach_header_t *)mh,
- kext_map, start, size, seg->maxprot, TRUE, type);
- if (ret != KERN_SUCCESS) {
- printf("OSKext protect failed with error %d", ret);
- return kOSKextReturnInvalidArgument;
- }
-
- ret = OSKext_protect((kernel_mach_header_t *)mh,
- kext_map, start, size, seg->initprot, FALSE, type);
- if (ret != KERN_SUCCESS) {
- printf("OSKext protect failed with error %d", ret);
- return kOSKextReturnInvalidArgument;
- }
-
- ret = OSKext_wire((kernel_mach_header_t *)mh,
- kext_map, start, end, seg->initprot, FALSE, type);
- if (ret != KERN_SUCCESS) {
- printf("OSKext wire failed with error %d", ret);
- return kOSKextReturnInvalidArgument;
- }
- }
-
- seg = nextsegfromheader((kernel_mach_header_t *) mh, seg);
- }
-
- return 0;
-}
-
-/*********************************************************************
-* Assumes sKextLock is held.
-*********************************************************************/
-/* static */
-void
-OSKext::freeKCFileSetcontrol(void)
-{
- PE_reset_all_kc_vp();
-}
-
-/*********************************************************************
-* Assumes sKextLock is held.
-*
-* resetKCFileSetSegments: Kext start function expects data segment to
-* be pristine on every load, unmap the dirty segments on unload and
-* remap them from FileSet on disk. Remap all segments of kext since
-* fixups are done per kext and not per segment.
-*********************************************************************/
-OSReturn
-OSKext::resetKCFileSetSegments(void)
-{
- kernel_segment_command_t *seg = NULL;
- kernel_segment_command_t *text_seg;
- uint32_t text_fileoff;
- kernel_mach_header_t *k_mh = NULL;
- uintptr_t slide;
- struct vnode *vp = NULL;
- void *fileset_control = NULL;
- bool pageable = (kc_type == KCKindPageable);
- OSReturn err;
- kern_return_t kr;
-
- /* Check the vnode reference is still available */
- vp = (struct vnode *)PE_get_kc_vp(kc_type);
- if (vp == NULL) {
- OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag,
- "Kext %s could not be reset, since reboot released the vnode ref", getIdentifierCString());
- return kOSKextReturnInternalError;
- }
-
- fileset_control = ubc_getobject(vp, 0);
- assert(fileset_control != NULL);
-
- OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag,
- "Kext %s resetting all segments", getIdentifierCString());
-
- k_mh = (kernel_mach_header_t *)kmod_info->address;
- text_seg = getsegbynamefromheader((kernel_mach_header_t *)kmod_info->address, SEG_TEXT);
- text_fileoff = text_seg->fileoff;
- slide = PE_get_kc_slide(kc_type);
-
- seg = firstsegfromheader((kernel_mach_header_t *)k_mh);
- while (seg) {
- if (seg->vmsize == 0) {
- seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
- continue;
- }
-
- /* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */
- if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 ||
- strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 ||
- strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) {
- seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
- continue;
- }
-
- kr = vm_unmap_kcfileset_segment(&seg->vmaddr, seg->vmsize);
- assert(kr == KERN_SUCCESS);
- seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
- }
-
- /* Unmap the text segment */
- kr = vm_unmap_kcfileset_segment(&text_seg->vmaddr, text_seg->vmsize);
- assert(kr == KERN_SUCCESS);
-
- /* Map all the segments of the kext */
- err = OSKext::mapKCFileSet(fileset_control, 0, &k_mh, text_fileoff, &slide, pageable, NULL);
- if (err) {
- panic("Could not reset segments of a mapped kext, error %x", err);
- }
-
- /* Update address in kmod_info, since it has been reset */
- if (kmod_info->address) {
- kmod_info->address = (((uintptr_t)(kmod_info->address)) + slide);
- }
-
- return 0;
-}
-
-/*********************************************************************
-* Mechanism to track all segment mapping while mapping KC fileset.
-*********************************************************************/
-
-struct kcfileset_map_entry {
- vm_map_offset_t me_start;
- vm_map_offset_t me_size;
-};
-
-struct kcfileset_map_entry_list {
- int kme_list_count;
- int kme_list_index;
- struct kcfileset_map_entry kme_list[];
-};
-
-#define KCFILESET_MAP_ENTRY_MAX (16380)
-
-static void *
-allocate_kcfileset_map_entry_list(void)
-{
- struct kcfileset_map_entry_list *entry_list;
-
- entry_list = kalloc_type(struct kcfileset_map_entry_list,
- struct kcfileset_map_entry, KCFILESET_MAP_ENTRY_MAX, Z_WAITOK_ZERO);
-
- entry_list->kme_list_count = KCFILESET_MAP_ENTRY_MAX;
- entry_list->kme_list_index = 0;
- return entry_list;
-}
-
-static void
-add_kcfileset_map_entry(
- void *map_entry_list,
- vm_map_offset_t start,
- vm_map_offset_t size)
-{
- if (map_entry_list == NULL) {
- return;
- }
-
- struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list;
-
- if (entry_list->kme_list_index >= entry_list->kme_list_count) {
- panic("Ran out of map kc fileset list");
- }
-
- entry_list->kme_list[entry_list->kme_list_index].me_start = start;
- entry_list->kme_list[entry_list->kme_list_index].me_size = size;
-
- entry_list->kme_list_index++;
-}
-
-static void
-deallocate_kcfileset_map_entry_list_and_unmap_entries(
- void *map_entry_list,
- boolean_t unmap_entries,
- bool pageable)
-{
- struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list;
-
- if (unmap_entries) {
- for (int i = 0; i < entry_list->kme_list_index; i++) {
- kern_return_t ret;
- ret = vm_unmap_kcfileset_segment(
- &(entry_list->kme_list[i].me_start),
- entry_list->kme_list[i].me_size);
- assert(ret == KERN_SUCCESS);
- }
-
- PE_reset_kc_header(pageable ? KCKindPageable : KCKindAuxiliary);
- }
-
- kfree_type(struct kcfileset_map_entry_list, struct kcfileset_map_entry,
- KCFILESET_MAP_ENTRY_MAX, entry_list);
-}
-
-/*********************************************************************
-* Mechanism to map kext segment.
-*********************************************************************/
-
-kern_return_t
-vm_map_kcfileset_segment(
- vm_map_offset_t *start,
- vm_map_offset_t size,
- void *control,
- vm_object_offset_t fileoffset,
- vm_prot_t max_prot)
-{
- vm_map_kernel_flags_t vmk_flags = {
- .vmf_fixed = true,
- .vmkf_no_copy_on_read = true,
- .vmkf_cs_enforcement_override = true,
- .vm_tag = VM_KERN_MEMORY_OSKEXT,
- };
- kern_return_t ret;
-
- /* Add Write to max prot to allow fixups */
- max_prot = max_prot | VM_PROT_WRITE;
-
- /*
- * Map the segments from file as COPY mappings to
- * make sure changes on disk to the file does not affect
- * mapped segments.
- */
- ret = vm_map_enter_mem_object_control(
- g_kext_map,
- start,
- size,
- (mach_vm_offset_t)0,
- vmk_flags,
- (memory_object_control_t)control,
- fileoffset,
- TRUE, /* copy */
- (VM_PROT_READ | VM_PROT_WRITE), max_prot,
- VM_INHERIT_NONE);
-
- return ret;
-}
-
-kern_return_t
-vm_unmap_kcfileset_segment(
- vm_map_offset_t *start,
- vm_map_offset_t size)
-{
- return mach_vm_deallocate(g_kext_map, *start, size);
-}
-
-#endif //(__x86_64__) || defined(__i386__)
-
-/*********************************************************************
-* Assumes sKextLock is held.
-*********************************************************************/
-/* static */
-OSReturn
-OSKext::validateKCFileSetUUID(
- OSDictionary *infoDict,
- kc_kind_t type)
-{
- OSReturn ret = kOSReturnSuccess;
-
- if (!kernelcache_uuid_valid) {
- OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
- "validateKCFileSetUUID Boot KC UUID was not set at boot.");
- ret = kOSKextReturnInvalidArgument;
- goto finish;
- }
- ret = OSKext::validateKCUUIDfromPrelinkInfo(&kernelcache_uuid, type, infoDict, kPrelinkInfoBootKCIDKey);
- if (ret != 0) {
- goto finish;
- }
-
-#if defined(__x86_64__) || defined(__i386__)
- /* Check if the Aux KC is prelinked to correct Pageable KC */
- if (type == KCKindAuxiliary) {
- if (!pageablekc_uuid_valid) {
- OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
- "validateKCFileSetUUID Pageable KC UUID was not set while loading Pageable KC.");
- ret = kOSKextReturnInvalidArgument;
- goto finish;
- }
- ret = OSKext::validateKCUUIDfromPrelinkInfo(&pageablekc_uuid, type, infoDict, kPrelinkInfoPageableKCIDKey);
- if (ret != 0) {
- goto finish;
- }
- }
-#endif //(__x86_64__) || defined(__i386__)
-
- printf("KextLog: Collection UUID matches with loaded KCs.\n");
-finish:
- return ret;
-}
-
-/*********************************************************************
-* Assumes sKextLock is held.
-*********************************************************************/
-/* static */
-OSReturn
-OSKext::validateKCUUIDfromPrelinkInfo(
- uuid_t *loaded_kcuuid,
- kc_kind_t type,
- OSDictionary *infoDict,
- const char *uuid_key)
-{
- /* extract the UUID from the dictionary */
- OSData *prelinkinfoKCUUID = OSDynamicCast(OSData, infoDict->getObject(uuid_key));
- if (!prelinkinfoKCUUID) {
- OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
- "validateKCUUID Info plist does not contain %s KC UUID key.", uuid_key);
- return kOSKextReturnInvalidArgument;
- }
-
- if (prelinkinfoKCUUID->getLength() != sizeof(uuid_t)) {
- OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
- "validateKCUUID %s KC UUID has wrong length: %d.", uuid_key, prelinkinfoKCUUID->getLength());
- return kOSKextReturnInvalidArgument;
- }
-
- if (memcmp((void *)loaded_kcuuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(),
- prelinkinfoKCUUID->getLength())) {
- OSData *info_dict_uuid;
- uuid_string_t info_dict_uuid_str = {};
- uuid_string_t expected_uuid_str = {};
- uuid_string_t given_uuid_str = {};
- uuid_t given_uuid;
-
- /* extract the KC UUID from the dictionary */
- info_dict_uuid = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
- if (info_dict_uuid && info_dict_uuid->getLength() == sizeof(uuid_t)) {
- uuid_t tmp_uuid;
- memcpy(tmp_uuid, (const void *)info_dict_uuid->getBytesNoCopy(), sizeof(tmp_uuid));
- uuid_unparse(tmp_uuid, info_dict_uuid_str);
- }
-
- uuid_unparse(*loaded_kcuuid, expected_uuid_str);
- memcpy(given_uuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(), sizeof(given_uuid));
- uuid_unparse(given_uuid, given_uuid_str);
-
- printf("KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key,
- given_uuid_str, expected_uuid_str, info_dict_uuid_str);
- OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
- "KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key,
- given_uuid_str, expected_uuid_str, info_dict_uuid_str);
- if (type == KCKindPageable && sPanicOnKCMismatch) {
- panic("System KC UUID %s linked against %s, but %s is loaded",
- info_dict_uuid_str, given_uuid_str, expected_uuid_str);
- }
- return kOSKextReturnInvalidArgument;
- }
-
- return 0;
}
/*********************************************************************
@@ -14322,17 +10064,17 @@
OSKext::dispatchResource(OSDictionary * requestDict)
{
OSReturn result = kOSReturnError;
- OSSharedPtr<OSDictionary> callbackRecord;
- OSNumber * requestTag = NULL; // do not release
- OSNumber * requestResult = NULL; // do not release
- OSData * dataObj = NULL; // do not release
+ OSDictionary * callbackRecord = NULL;// must release
+ OSNumber * requestTag = NULL;// do not release
+ OSNumber * requestResult = NULL;// do not release
+ OSData * dataObj = NULL;// do not release
uint32_t dataLength = 0;
- const void * dataPtr = NULL; // do not free
- OSValueObject<OSKextRequestResourceCallback> * callbackWrapper = nullptr; // do not release
+ const void * dataPtr = NULL;// do not free
+ OSData * callbackWrapper = NULL;// do not release
OSKextRequestResourceCallback callback = NULL;
- OSValueObject<void *> * contextWrapper = nullptr; // do not release
- void * context = NULL; // do not free
- OSSharedPtr<OSKext> callbackKext;
+ OSData * contextWrapper = NULL;// do not release
+ void * context = NULL;// do not free
+ OSKext * callbackKext = NULL;// must release (looked up)
/* Get the args from the request. Right now we need the tag
* to look up the callback record, and the result for invoking the callback.
@@ -14348,7 +10090,7 @@
/* Look for a callback record matching this request's tag.
*/
- result = dequeueCallbackForRequestTag(requestTag, callbackRecord);
+ result = dequeueCallbackForRequestTag(requestTag, &callbackRecord);
if (result != kOSReturnSuccess) {
goto finish;
}
@@ -14356,17 +10098,18 @@
/*****
* Get the context pointer of the callback record (if there is one).
*/
- contextWrapper = OSDynamicCast(OSValueObject<void *>, _OSKextGetRequestArgument(
- callbackRecord.get(), kKextRequestArgumentContextKey));
+ contextWrapper = OSDynamicCast(OSData, _OSKextGetRequestArgument(callbackRecord,
+ kKextRequestArgumentContextKey));
context = _OSKextExtractPointer(contextWrapper);
if (contextWrapper && !context) {
goto finish;
}
- callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
- _OSKextGetRequestArgument(callbackRecord.get(),
+ callbackWrapper = OSDynamicCast(OSData,
+ _OSKextGetRequestArgument(callbackRecord,
kKextRequestArgumentCallbackKey));
- callback = _OSKextExtractCallbackPointer(callbackWrapper);
+ callback = (OSKextRequestResourceCallback)
+ _OSKextExtractPointer(callbackWrapper);
if (!callback) {
goto finish;
}
@@ -14403,81 +10146,14 @@
result = kOSReturnSuccess;
finish:
+ if (callbackKext) {
+ callbackKext->release();
+ }
+ if (callbackRecord) {
+ callbackRecord->release();
+ }
+
return result;
-}
-
-/*********************************************************************
-* Assumes sKextLock is held.
-*********************************************************************/
-/* static */
-OSReturn
-OSKext::setMissingAuxKCBundles(OSDictionary * requestDict)
-{
- OSSharedPtr<OSDictionary> missingIDs;
- OSArray *bundleIDList = NULL; // do not release
-
- bundleIDList = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
- requestDict, kKextRequestArgumentMissingBundleIDs));
- if (!bundleIDList) {
- return kOSKextReturnInvalidArgument;
- }
-
- missingIDs = OSDictionary::withCapacity(bundleIDList->getCount());
- if (!missingIDs) {
- return kOSKextReturnNoMemory;
- }
-
- uint32_t count, i;
- count = bundleIDList->getCount();
- for (i = 0; i < count; i++) {
- OSString *thisID = OSDynamicCast(OSString, bundleIDList->getObject(i));
- if (thisID) {
- missingIDs->setObject(thisID, kOSBooleanFalse);
- }
- }
-
- sNonLoadableKextsByID.reset(missingIDs.get(), OSRetain);
-
- return kOSReturnSuccess;
-}
-
-/*********************************************************************
-* Assumes sKextLock is held.
-*********************************************************************/
-/* static */
-OSReturn
-OSKext::setAuxKCBundleAvailable(OSString *kextIdentifier, OSDictionary *requestDict)
-{
- bool loadable = true;
- if (!kextIdentifier) {
- return kOSKextReturnInvalidArgument;
- }
-
- if (requestDict) {
- OSBoolean *loadableArg;
- loadableArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
- requestDict, kKextRequestArgumentBundleAvailability));
- /* If we find the "Bundle Available" arg, and it's false, then
- * mark the bundle ID as _not_ loadable
- */
- if (loadableArg && !loadableArg->getValue()) {
- loadable = false;
- }
- }
-
- if (!sNonLoadableKextsByID) {
- sNonLoadableKextsByID = OSDictionary::withCapacity(1);
- }
-
- sNonLoadableKextsByID->setObject(kextIdentifier, OSBoolean::withBoolean(loadable));
-
- OSKextLog(/* kext */ NULL,
- kOSKextLogBasicLevel | kOSKextLogIPCFlag,
- "KextLog: AuxKC bundle %s marked as %s",
- kextIdentifier->getCStringNoCopy(),
- (loadable ? "loadable" : "NOT loadable"));
-
- return kOSReturnSuccess;
}
/*********************************************************************
@@ -14489,7 +10165,7 @@
OSReturn callbackResult)
{
OSString * predicate = _OSKextGetRequestPredicate(callbackRecord);
- OSSharedPtr<OSNumber> resultNum;
+ OSNumber * resultNum = NULL;// must release
if (!predicate) {
goto finish;
@@ -14505,7 +10181,7 @@
* were the reply coming down from user space.
*/
_OSKextSetRequestArgument(callbackRecord, kKextRequestArgumentResultKey,
- resultNum.get());
+ resultNum);
if (predicate->isEqualTo(kKextRequestPredicateRequestResource)) {
/* This removes the pending callback record.
@@ -14514,6 +10190,9 @@
}
finish:
+ if (resultNum) {
+ resultNum->release();
+ }
return;
}
@@ -14527,19 +10206,23 @@
void ** contextOut)
{
OSReturn result = kOSKextReturnNoMemory;
- OSSharedPtr<OSDictionary> callbackRecord;
- OSValueObject<void *> * contextWrapper = nullptr; // do not release
+ OSDictionary * callbackRecord = NULL; // must release
+ OSData * contextWrapper = NULL;// do not release
IORecursiveLockLock(sKextLock);
result = OSKext::dequeueCallbackForRequestTag(requestTag,
- callbackRecord);
+ &callbackRecord);
IORecursiveLockUnlock(sKextLock);
if (result == kOSReturnSuccess && contextOut) {
- contextWrapper = OSDynamicCast(OSValueObject<void *>,
- _OSKextGetRequestArgument(callbackRecord.get(),
+ contextWrapper = OSDynamicCast(OSData,
+ _OSKextGetRequestArgument(callbackRecord,
kKextRequestArgumentContextKey));
*contextOut = _OSKextExtractPointer(contextWrapper);
+ }
+
+ if (callbackRecord) {
+ callbackRecord->release();
}
return result;
@@ -14568,7 +10251,7 @@
if (!request) {
continue;
}
- auto * callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
+ OSData * callbackWrapper = OSDynamicCast(OSData,
_OSKextGetRequestArgument(request,
kKextRequestArgumentCallbackKey));
@@ -14578,7 +10261,7 @@
}
vm_address_t callbackAddress = (vm_address_t)
- ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer);
+ _OSKextExtractPointer(callbackWrapper);
if ((kmod_info->address <= callbackAddress) &&
(callbackAddress < (kmod_info->address + kmod_info->size))) {
@@ -14618,7 +10301,7 @@
if (!request) {
continue;
}
- auto * callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
+ OSData * callbackWrapper = OSDynamicCast(OSData,
_OSKextGetRequestArgument(request,
kKextRequestArgumentCallbackKey));
@@ -14627,7 +10310,7 @@
}
vm_address_t callbackAddress = (vm_address_t)
- ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer);
+ _OSKextExtractPointer(callbackWrapper);
if ((kmod_info->address <= callbackAddress) &&
(callbackAddress < (kmod_info->address + kmod_info->size))) {
@@ -14644,16 +10327,16 @@
static OSReturn
_OSKextCreateRequest(
const char * predicate,
- OSSharedPtr<OSDictionary> & requestR)
+ OSDictionary ** requestP)
{
OSReturn result = kOSKextReturnNoMemory;
- OSSharedPtr<OSDictionary> request;
+ OSDictionary * request = NULL; // must release on error
request = OSDictionary::withCapacity(2);
if (!request) {
goto finish;
}
- result = _OSDictionarySetCStringValue(request.get(),
+ result = _OSDictionarySetCStringValue(request,
kKextRequestPredicateKey, predicate);
if (result != kOSReturnSuccess) {
goto finish;
@@ -14661,8 +10344,12 @@
result = kOSReturnSuccess;
finish:
- if (result == kOSReturnSuccess) {
- requestR = os::move(request);
+ if (result != kOSReturnSuccess) {
+ if (request) {
+ request->release();
+ }
+ } else {
+ *requestP = request;
}
return result;
@@ -14696,20 +10383,19 @@
*********************************************************************/
static bool
_OSKextSetRequestArgument(
- OSDictionary * requestDict,
- const char * argName,
- OSMetaClassBase * value)
+ OSDictionary * requestDict,
+ const char * argName,
+ OSObject * value)
{
OSDictionary * args = OSDynamicCast(OSDictionary,
requestDict->getObject(kKextRequestArgumentsKey));
- OSSharedPtr<OSDictionary> newArgs;
if (!args) {
- newArgs = OSDictionary::withCapacity(2);
- args = newArgs.get();
+ args = OSDictionary::withCapacity(2);
if (!args) {
goto finish;
}
requestDict->setObject(kKextRequestArgumentsKey, args);
+ args->release();
}
if (args) {
return args->setObject(argName, value);
@@ -14720,27 +10406,20 @@
/*********************************************************************
*********************************************************************/
-template <typename T>
-static T *
-_OSKextExtractPointer(OSValueObject<T *> * wrapper)
-{
+static void *
+_OSKextExtractPointer(OSData * wrapper)
+{
+ void * result = NULL;
+ const void * resultPtr = NULL;
+
if (!wrapper) {
- return nullptr;
- }
- return wrapper->getRef();
-}
-
-/*********************************************************************
-*********************************************************************/
-static OSKextRequestResourceCallback
-_OSKextExtractCallbackPointer(OSValueObject<OSKextRequestResourceCallback> * wrapper)
-{
- if (!wrapper) {
- return nullptr;
- }
- return wrapper->getRef();
-}
-
+ goto finish;
+ }
+ resultPtr = wrapper->getBytesNoCopy();
+ result = *(void **)resultPtr;
+finish:
+ return result;
+}
/*********************************************************************
*********************************************************************/
@@ -14751,19 +10430,26 @@
const char * cValue)
{
OSReturn result = kOSKextReturnNoMemory;
- OSSharedPtr<const OSSymbol> key;
- OSSharedPtr<OSString> value;
+ const OSSymbol * key = NULL; // must release
+ OSString * value = NULL; // must release
key = OSSymbol::withCString(cKey);
value = OSString::withCString(cValue);
if (!key || !value) {
goto finish;
}
- if (dict->setObject(key.get(), value.get())) {
+ if (dict->setObject(key, value)) {
result = kOSReturnSuccess;
}
finish:
+ if (key) {
+ key->release();
+ }
+ if (value) {
+ value->release();
+ }
+
return result;
}
@@ -14775,7 +10461,7 @@
const char * cString)
{
bool result = false;
- OSSharedPtr<const OSSymbol> symbol;
+ const OSSymbol * symbol = NULL;
uint32_t count, i;
if (!array || !cString) {
@@ -14797,10 +10483,12 @@
}
finish:
+ if (symbol) {
+ symbol->release();
+ }
return result;
}
-#if CONFIG_KXLD
/*********************************************************************
* We really only care about boot / system start up related kexts.
* We return true if we're less than REBUILD_MAX_TIME since start up,
@@ -14826,7 +10514,6 @@
}
return true;
}
-#endif /* CONFIG_KXLD */
/*********************************************************************
*********************************************************************/
@@ -14847,7 +10534,7 @@
}
for (i = 0; i < unLoadedCount; i++) {
- const OSSymbol * myBundleID; // do not release
+ const OSSymbol * myBundleID;// do not release
myBundleID = OSDynamicCast(OSSymbol, sUnloadedPrelinkedKexts->getObject(i));
if (!myBundleID) {
@@ -14869,15 +10556,16 @@
/*********************************************************************
*********************************************************************/
/* static */
-OSSharedPtr<OSArray>
+OSArray *
OSKext::copyAllKextPersonalities(bool filterSafeBootFlag)
{
- OSSharedPtr<OSArray> result;
- OSSharedPtr<OSCollectionIterator> kextIterator;
- OSSharedPtr<OSArray> personalities;
-
- OSString * kextID = NULL; // do not release
- OSKext * theKext = NULL; // do not release
+ OSArray * result = NULL;// returned
+ OSCollectionIterator * kextIterator = NULL;// must release
+ OSArray * personalities = NULL;// must release
+ OSCollectionIterator * personalitiesIterator = NULL; // must release
+
+ OSString * kextID = NULL;// do not release
+ OSKext * theKext = NULL;// do not release
IORecursiveLockLock(sKextLock);
@@ -14889,26 +10577,28 @@
goto finish;
}
- kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
+ kextIterator = OSCollectionIterator::withCollection(sKextsByID);
if (!kextIterator) {
goto finish;
}
while ((kextID = OSDynamicCast(OSString, kextIterator->getNextObject()))) {
+ if (personalitiesIterator) {
+ personalitiesIterator->release();
+ personalitiesIterator = NULL;
+ }
+ if (personalities) {
+ personalities->release();
+ personalities = NULL;
+ }
+
theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextID));
- if (theKext->flags.requireExplicitLoad) {
- OSKextLog(theKext,
- kOSKextLogDebugLevel |
- kOSKextLogLoadFlag,
- "Kext %s requires an explicit kextload; "
- "omitting its personalities.",
- theKext->getIdentifierCString());
- } else if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) {
+ if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) {
personalities = theKext->copyPersonalitiesArray();
if (!personalities) {
continue;
}
- result->merge(personalities.get());
+ result->merge(personalities);
} else {
// xxx - check for better place to put this log msg
OSKextLog(theKext,
@@ -14923,6 +10613,16 @@
finish:
IORecursiveLockUnlock(sKextLock);
+ if (kextIterator) {
+ kextIterator->release();
+ }
+ if (personalitiesIterator) {
+ personalitiesIterator->release();
+ }
+ if (personalities) {
+ personalities->release();
+ }
+
return result;
}
@@ -14941,12 +10641,13 @@
"to the IOCatalogue %s.",
startMatching ? "and starting matching" : "but not starting matching");
- OSSharedPtr<OSArray> personalities = OSKext::copyAllKextPersonalities(
+ OSArray * personalities = OSKext::copyAllKextPersonalities(
/* filterSafeBootFlag */ true);
if (personalities) {
- gIOCatalogue->addDrivers(personalities.get(), startMatching);
+ gIOCatalogue->addDrivers(personalities, startMatching);
numPersonalities = personalities->getCount();
+ personalities->release();
}
OSKextLog(/* kext */ NULL,
@@ -14962,15 +10663,15 @@
* Do not make a deep copy, just convert the IOKitPersonalities dict
* to an array for sending to the IOCatalogue.
*********************************************************************/
-OSSharedPtr<OSArray>
+OSArray *
OSKext::copyPersonalitiesArray(void)
{
- OSSharedPtr<OSArray> result;
- OSDictionary * personalities = NULL; // do not release
- OSSharedPtr<OSCollectionIterator> personalitiesIterator;
-
- OSString * personalityName = NULL; // do not release
- OSString * personalityBundleIdentifier = NULL; // do not release
+ OSArray * result = NULL;
+ OSDictionary * personalities = NULL;// do not release
+ OSCollectionIterator * personalitiesIterator = NULL;// must release
+
+ OSString * personalityName = NULL;// do not release
+ OSString * personalityBundleIdentifier = NULL;// do not release
personalities = OSDynamicCast(OSDictionary,
getPropertyForHostArch(kIOKitPersonalitiesKey));
@@ -14993,27 +10694,29 @@
OSDictionary * personality = OSDynamicCast(OSDictionary,
personalities->getObject(personalityName));
- if (personality) {
- /******
- * If the personality doesn't have a CFBundleIdentifier, or if it
- * differs from the kext's, insert the kext's ID so we can find it.
- * The publisher ID is used to remove personalities from bundles
- * correctly.
- */
- personalityBundleIdentifier = OSDynamicCast(OSString,
- personality->getObject(kCFBundleIdentifierKey));
-
- if (!personalityBundleIdentifier) {
- personality->setObject(kCFBundleIdentifierKey, bundleID.get());
- } else if (!personalityBundleIdentifier->isEqualTo(bundleID.get())) {
- personality->setObject(kIOPersonalityPublisherKey, bundleID.get());
- }
+ /******
+ * If the personality doesn't have a CFBundleIdentifier, or if it
+ * differs from the kext's, insert the kext's ID so we can find it.
+ * The publisher ID is used to remove personalities from bundles
+ * correctly.
+ */
+ personalityBundleIdentifier = OSDynamicCast(OSString,
+ personality->getObject(kCFBundleIdentifierKey));
+
+ if (!personalityBundleIdentifier) {
+ personality->setObject(kCFBundleIdentifierKey, bundleID);
+ } else if (!personalityBundleIdentifier->isEqualTo(bundleID)) {
+ personality->setObject(kIOPersonalityPublisherKey, bundleID);
}
result->setObject(personality);
}
finish:
+ if (personalitiesIterator) {
+ personalitiesIterator->release();
+ }
+
return result;
}
@@ -15026,8 +10729,8 @@
OSArray * personalityNames)
{
OSReturn result = kOSReturnSuccess;
- OSSharedPtr<OSArray> personalitiesToSend;
- OSDictionary * kextPersonalities = NULL; // do not release
+ OSArray * personalitiesToSend = NULL;// must release
+ OSDictionary * kextPersonalities = NULL;// do not release
int count, i;
if (!sLoadEnabled) {
@@ -15089,9 +10792,12 @@
numPersonalities,
numPersonalities > 1 ? "ies" : "y",
startMatching ? " and starting matching" : " but not starting matching");
- gIOCatalogue->addDrivers(personalitiesToSend.get(), startMatching);
+ gIOCatalogue->addDrivers(personalitiesToSend, startMatching);
}
finish:
+ if (personalitiesToSend) {
+ personalitiesToSend->release();
+ }
return result;
}
@@ -15102,7 +10808,7 @@
void
OSKext::removePersonalitiesFromCatalog(void)
{
- OSSharedPtr<OSDictionary> personality;
+ OSDictionary * personality = NULL; // do not release
personality = OSDictionary::withCapacity(1);
if (!personality) {
@@ -15119,32 +10825,16 @@
/* Have the IOCatalog remove all personalities matching this kext's
* bundle ID and trigger matching anew.
*/
- gIOCatalogue->removeDrivers(personality.get(), /* startMatching */ true);
+ gIOCatalogue->removeDrivers(personality, /* startMatching */ true);
finish:
+ if (personality) {
+ personality->release();
+ }
+
return;
}
-void
-OSKext::updatePersonalitiesInCatalog(OSArray *upgradedPersonalities)
-{
- if (!upgradedPersonalities || upgradedPersonalities->getCount() == 0) {
- return;
- }
-
- OSSharedPtr<OSDictionary> personalityToRemove = OSDictionary::withCapacity(1);
- if (!personalityToRemove) {
- return;
- }
-
- /*
- * Create a personality dictionary with just the bundleID.
- * We will remove any personality that has a matching bundleID,
- * irrespective of which other keys are present on the dictionary.
- */
- personalityToRemove->setObject(kCFBundleIdentifierKey, getIdentifier());
- gIOCatalogue->exchangeDrivers(personalityToRemove.get(), upgradedPersonalities, true);
-}
#if PRAGMA_MARK
#pragma mark Logging
@@ -15176,6 +10866,8 @@
sUserSpaceLogMessageArray = OSArray::withCapacity(0);
if (!sUserSpaceLogSpecArray || !sUserSpaceLogMessageArray) {
+ OSSafeReleaseNULL(sUserSpaceLogSpecArray);
+ OSSafeReleaseNULL(sUserSpaceLogMessageArray);
allocError = true;
}
}
@@ -15207,10 +10899,10 @@
* Do not call any function that takes sKextLock here!
*********************************************************************/
/* static */
-OSSharedPtr<OSArray>
+OSArray *
OSKext::clearUserSpaceLogFilter(void)
{
- OSSharedPtr<OSArray> result;
+ OSArray * result = NULL;
OSKextLogSpec oldLogFilter;
OSKextLogSpec newLogFilter = kOSKextLogSilentFilter;
@@ -15221,11 +10913,11 @@
result = OSArray::withCapacity(2);
if (result) {
- result->setObject(sUserSpaceLogSpecArray.get());
- result->setObject(sUserSpaceLogMessageArray.get());
- }
- sUserSpaceLogSpecArray.reset();
- sUserSpaceLogMessageArray.reset();
+ result->setObject(sUserSpaceLogSpecArray);
+ result->setObject(sUserSpaceLogMessageArray);
+ }
+ OSSafeReleaseNULL(sUserSpaceLogSpecArray);
+ OSSafeReleaseNULL(sUserSpaceLogMessageArray);
oldLogFilter = sUserSpaceKextLogFilter;
sUserSpaceKextLogFilter = newLogFilter;
@@ -15304,7 +10996,7 @@
case kOSKextLogDebugLevel:
return VTMAGENTA;
default:
- return ""; // white
+ return ""; // white
}
}
@@ -15372,15 +11064,17 @@
const char * format,
va_list srcArgList)
{
+ extern int disableConsoleOutput;
+
bool logForKernel = false;
bool logForUser = false;
va_list argList;
char stackBuffer[120];
uint32_t length = 0;
- char * allocBuffer = NULL; // must kfree
- OSSharedPtr<OSNumber> logSpecNum;
- OSSharedPtr<OSString> logString;
- char * buffer = stackBuffer; // do not free
+ char * allocBuffer = NULL; // must kfree
+ OSNumber * logSpecNum = NULL; // must release
+ OSString * logString = NULL; // must release
+ char * buffer = stackBuffer;// do not free
IOLockLock(sKextLoggingLock);
@@ -15407,8 +11101,7 @@
va_end(argList);
if (length + 1 >= sizeof(stackBuffer)) {
- allocBuffer = (char *)kalloc_data_tag(length + 1,
- Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
+ allocBuffer = (char *)kalloc_tag((length + 1) * sizeof(char), VM_KERN_MEMORY_OSKEXT);
if (!allocBuffer) {
goto finish;
}
@@ -15428,8 +11121,8 @@
logSpecNum = OSNumber::withNumber(msgLogSpec, 8 * sizeof(msgLogSpec));
logString = OSString::withCString(buffer);
if (logSpecNum && logString) {
- sUserSpaceLogSpecArray->setObject(logSpecNum.get());
- sUserSpaceLogMessageArray->setObject(logString.get());
+ sUserSpaceLogSpecArray->setObject(logSpecNum);
+ sUserSpaceLogMessageArray->setObject(logString);
}
}
@@ -15440,8 +11133,8 @@
/* If we are in console mode and have a custom log filter,
* colorize the log message.
*/
- if (sBootArgLogFilterFound) {
- const char * color = ""; // do not free
+ if (!disableConsoleOutput && sBootArgLogFilterFound) {
+ const char * color = ""; // do not free
color = colorForFlags(msgLogSpec);
printf("%s%s%s\n", colorForFlags(msgLogSpec),
buffer, color[0] ? VTRESET : "");
@@ -15454,8 +11147,10 @@
IOLockUnlock(sKextLoggingLock);
if (allocBuffer) {
- kfree_data(allocBuffer, length + 1);
- }
+ kfree(allocBuffer, (length + 1) * sizeof(char));
+ }
+ OSSafeReleaseNULL(logString);
+ OSSafeReleaseNULL(logSpecNum);
return;
}
@@ -15482,7 +11177,7 @@
int indent)
{
const OSMetaClass * myTypeID;
- OSSharedPtr<OSCollectionIterator> myIter;
+ OSCollectionIterator * myIter;
OSSymbol * myKey;
OSObject * myValue;
bool myResult = false;
@@ -15503,8 +11198,6 @@
if (myIter == NULL) {
return myResult;
}
-
- // !! reset the iterator
myIter->reset();
while ((myKey = OSDynamicCast(OSSymbol, myIter->getNextObject()))) {
@@ -15519,9 +11212,7 @@
IOLog("OSDictionary key \"%s\" \n", myKey->getCStringNoCopy());
}
}
-
- // !! release the iterator
- myIter.reset();
+ myIter->release();
} else if (myTypeID == OSTypeID(OSArray)) {
OSArray * myArray;
@@ -15530,7 +11221,6 @@
if (myIter == NULL) {
return myResult;
}
- // !! reset the iterator
myIter->reset();
while ((myValue = myIter->getNextObject())) {
@@ -15543,8 +11233,7 @@
IOLog("OSArray: \n");
}
}
- // !! release the iterator
- myIter.reset();
+ myIter->release();
} else if (myTypeID == OSTypeID(OSString) || myTypeID == OSTypeID(OSSymbol)) {
// should we look for addresses in strings?
} else if (myTypeID == OSTypeID(OSData)) {
@@ -15566,17 +11255,18 @@
if (kext_alloc_max != 0 &&
numberValue >= kext_alloc_base &&
numberValue < kext_alloc_max) {
- OSSharedPtr<OSKext> myKext;
- // IOLog("found OSData %p in kext map %p to %p \n",
- // *(myPtrPtr),
- // (void *) kext_alloc_base,
- // (void *) kext_alloc_max);
+ OSKext * myKext = NULL;// must release (looked up)
+ // IOLog("found OSData %p in kext map %p to %p \n",
+ // *(myPtrPtr),
+ // (void *) kext_alloc_base,
+ // (void *) kext_alloc_max);
myKext = OSKext::lookupKextWithAddress((vm_address_t) *(myPtrPtr));
if (myKext) {
IOLog("found addr %p from an OSData obj within kext \"%s\" \n",
*(myPtrPtr),
myKext->getIdentifierCString());
+ myKext->release();
}
myResult = true;
}
@@ -15602,7 +11292,7 @@
if (kext_alloc_max != 0 &&
numberValue >= kext_alloc_base &&
numberValue < kext_alloc_max) {
- OSSharedPtr<OSKext> myKext;
+ OSKext * myKext = NULL;// must release (looked up)
IOLog("found OSNumber in kext map %p to %p \n",
(void *) kext_alloc_base,
(void *) kext_alloc_max);
@@ -15612,6 +11302,7 @@
if (myKext) {
IOLog("found in kext \"%s\" \n",
myKext->getIdentifierCString());
+ myKext->release();
}
myResult = true;
@@ -15642,7 +11333,7 @@
return myResult;
}
#endif // KASLR_KEXT_DEBUG
-}; /* extern "C" */
+}; /* extern "C" */
#if PRAGMA_MARK
#pragma mark Backtrace Dump & kmod_get_info() support
@@ -15660,6 +11351,8 @@
{
addr64_t summary_page = 0;
addr64_t last_summary_page = 0;
+ bool found_kmod = false;
+ u_int i = 0;
if (kPrintKextsLock & flags) {
if (!sKextSummariesLock) {
@@ -15683,13 +11376,27 @@
}
}
- foreachKextInBacktrace(addr, cnt, 0, ^(OSKextLoadedKextSummary *summary, uint32_t index) {
- if (index == 0 && !(kPrintKextsTerse & flags)) {
- (*printf_func)(" Kernel Extensions in backtrace:\n");
+ for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
+ OSKextLoadedKextSummary * summary;
+
+ summary = gLoadedKextSummaries->summaries + i;
+ if (!summary->address) {
+ continue;
+ }
+
+ if (!summaryIsInBacktrace(summary, addr, cnt)) {
+ continue;
+ }
+
+ if (!found_kmod) {
+ if (!(kPrintKextsTerse & flags)) {
+ (*printf_func)(" Kernel Extensions in backtrace:\n");
+ }
+ found_kmod = true;
}
printSummary(summary, printf_func, flags);
- });
+ }
finish:
if (kPrintKextsLock & flags) {
@@ -15697,42 +11404,6 @@
}
return;
-}
-
-void
-OSKext::foreachKextInBacktrace(
- vm_offset_t * addr,
- uint32_t cnt,
- uint32_t flags,
- void (^ handler)(OSKextLoadedKextSummary *summary, uint32_t index))
-{
- uint32_t n = 0;
-
- if (kPrintKextsLock & flags) {
- if (!sKextSummariesLock) {
- return;
- }
- IOLockLock(sKextSummariesLock);
- }
-
- for (uint32_t i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
- OSKextLoadedKextSummary * summary;
-
- summary = gLoadedKextSummaries->summaries + i;
- if (!summary->address) {
- continue;
- }
-
- if (!summaryIsInBacktrace(summary, addr, cnt)) {
- continue;
- }
-
- handler(summary, n++);
- }
-
- if (kPrintKextsLock & flags) {
- IOLockUnlock(sKextSummariesLock);
- }
}
/*********************************************************************
@@ -15749,11 +11420,8 @@
for (i = 0; i < cnt; i++) {
vm_offset_t kscan_addr = addr[i];
-#if __has_feature(ptrauth_calls)
- kscan_addr = (vm_offset_t)VM_KERNEL_STRIP_PTR(kscan_addr);
-#endif /* __has_feature(ptrauth_calls) */
- if ((kscan_addr >= summary->text_exec_address) &&
- (kscan_addr < (summary->text_exec_address + summary->text_exec_size))) {
+ if ((kscan_addr >= summary->address) &&
+ (kscan_addr < (summary->address + summary->size))) {
return TRUE;
}
}
@@ -15766,11 +11434,8 @@
* sKextSummariesLock held.
*/
OSKextLoadedKextSummary *
-OSKext::summaryForAddress(uintptr_t addr)
-{
-#if __has_feature(ptrauth_calls)
- addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr);
-#endif /* __has_feature(ptrauth_calls) */
+OSKext::summaryForAddress(const uintptr_t addr)
+{
for (unsigned i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
OSKextLoadedKextSummary *summary = &gLoadedKextSummaries->summaries[i];
if (!summary->address) {
@@ -15806,31 +11471,26 @@
void *
OSKext::kextForAddress(const void *address)
{
+ void * image = NULL;
OSKextActiveAccount * active;
OSKext * kext = NULL;
uint32_t baseIdx;
uint32_t lim;
uintptr_t addr = (uintptr_t) address;
- size_t i;
if (!addr) {
return NULL;
}
-#if __has_feature(ptrauth_calls)
- addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr);
-#endif /* __has_feature(ptrauth_calls) */
if (sKextAccountsCount) {
- lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
+ IOSimpleLockLock(sKextAccountsLock);
// bsearch sKextAccounts list
for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
active = &sKextAccounts[baseIdx + (lim >> 1)];
if ((addr >= active->address) && (addr < active->address_end)) {
- if (active->account &&
- (kext = active->account->kext) &&
- kext->kmod_info) {
- lck_ticket_unlock(sKextAccountsLock);
- return (void *)kext->kmod_info->address;
+ kext = active->account->kext;
+ if (kext && kext->kmod_info) {
+ image = (void *) kext->kmod_info->address;
}
break;
} else if (addr > active->address) {
@@ -15840,75 +11500,43 @@
}
// else move left
}
- lck_ticket_unlock(sKextAccountsLock);
- }
- if (kernel_text_contains(addr)) {
- return (void *)&_mh_execute_header;
- }
- if (gLoadedKextSummaries) {
- IOLockLock(sKextSummariesLock);
- for (i = 0; i < gLoadedKextSummaries->numSummaries; i++) {
- OSKextLoadedKextSummary *summary = gLoadedKextSummaries->summaries + i;
- if (addr >= summary->address && addr < summary->address + summary->size) {
- void *kextAddress = (void *)summary->address;
- IOLockUnlock(sKextSummariesLock);
- return kextAddress;
- }
- }
- IOLockUnlock(sKextSummariesLock);
- }
-
- return NULL;
-}
-
-/* static */
-kern_return_t
-OSKext::summaryForAddressExt(
- const void * address,
- OSKextLoadedKextSummary * summary)
-{
- kern_return_t result = KERN_FAILURE;
- const OSKextLoadedKextSummary * foundSummary = NULL;
-
- /*
- * This needs to be safe to call even before the lock has been initialized
- * in OSKext::initialize(), as we might get here from the ksancov runtime
- * when instrumenting XNU itself with sanitizer coverage.
- */
- if (!sKextSummariesLock) {
- return result;
- }
-
- IOLockLock(sKextSummariesLock);
- if (gLoadedKextSummaries) {
- foundSummary = summaryForAddress((uintptr_t)address);
- if (foundSummary) {
- memcpy(summary, foundSummary, sizeof(*summary));
- result = KERN_SUCCESS;
- } else {
- result = KERN_NOT_FOUND;
- }
- }
- IOLockUnlock(sKextSummariesLock);
-
- return result;
-}
-
-/*
- * Find a OSKextLoadedKextSummary given the ID from a kmod_info_t *
- * Safe to call in panic context.
- */
-static OSKextLoadedKextSummary *
-findSummary(uint32_t tagID)
-{
- OSKextLoadedKextSummary * summary;
- for (size_t i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
+ IOSimpleLockUnlock(sKextAccountsLock);
+ }
+ if (!image && (addr >= vm_kernel_stext) && (addr < vm_kernel_etext)) {
+ image = (void *) &_mh_execute_header;
+ }
+
+ return image;
+}
+
+/*********************************************************************
+* scan list of loaded kext summaries looking for a load address match and if
+* found return the UUID C string. If not found then set empty string.
+*********************************************************************/
+static void findSummaryUUID(
+ uint32_t tag_ID,
+ uuid_string_t uuid);
+
+static void
+findSummaryUUID(
+ uint32_t tag_ID,
+ uuid_string_t uuid)
+{
+ u_int i;
+
+ uuid[0] = 0x00; // default to no UUID
+
+ for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
+ OSKextLoadedKextSummary * summary;
+
summary = gLoadedKextSummaries->summaries + i;
- if (summary->loadTag == tagID) {
- return summary;
- }
- }
- return NULL;
+
+ if (summary->loadTag == tag_ID) {
+ (void) uuid_unparse(summary->uuid, uuid);
+ break;
+ }
+ }
+ return;
}
/*********************************************************************
@@ -15924,28 +11552,21 @@
uuid_string_t uuid;
char version[kOSKextVersionMaxLength];
uint64_t tmpAddr;
- uint64_t tmpSize;
- OSKextLoadedKextSummary *dependencySummary;
if (!OSKextVersionGetString(summary->version, version, sizeof(version))) {
strlcpy(version, "unknown version", sizeof(version));
}
(void) uuid_unparse(summary->uuid, uuid);
-#if defined(__arm__) || defined(__arm64__)
- tmpAddr = summary->text_exec_address;
- tmpSize = summary->text_exec_size;
-#else
- tmpAddr = summary->address;
- tmpSize = summary->size;
-#endif
if (kPrintKextsUnslide & flags) {
- tmpAddr = ml_static_unslide(tmpAddr);
+ tmpAddr = ml_static_unslide(summary->address);
+ } else {
+ tmpAddr = summary->address;
}
(*printf_func)("%s%s(%s)[%s]@0x%llx->0x%llx\n",
(kPrintKextsTerse & flags) ? "" : " ",
summary->name, version, uuid,
- tmpAddr, tmpAddr + tmpSize - 1);
+ tmpAddr, tmpAddr + summary->size - 1);
if (kPrintKextsTerse & flags) {
return;
@@ -15973,32 +11594,24 @@
}
if (!rinfo->address) {
- continue; // skip fake entries for built-ins
- }
-
- dependencySummary = findSummary(rinfo->id);
- uuid[0] = 0x00;
- tmpAddr = rinfo->address;
- tmpSize = rinfo->size;
- if (dependencySummary) {
- (void) uuid_unparse(dependencySummary->uuid, uuid);
-#if defined(__arm__) || defined(__arm64__)
- tmpAddr = dependencySummary->text_exec_address;
- tmpSize = dependencySummary->text_exec_size;
-#endif
- }
+ continue; // skip fake entries for built-ins
+ }
+
+ /* locate UUID in gLoadedKextSummaries */
+ findSummaryUUID(rinfo->id, uuid);
if (kPrintKextsUnslide & flags) {
- tmpAddr = ml_static_unslide(tmpAddr);
- }
- (*printf_func)(" dependency: %s(%s)[%s]@%p->%p\n",
- rinfo->name, rinfo->version, uuid, tmpAddr, tmpAddr + tmpSize - 1);
+ tmpAddr = ml_static_unslide(rinfo->address);
+ } else {
+ tmpAddr = rinfo->address;
+ }
+ (*printf_func)(" dependency: %s(%s)[%s]@%p\n",
+ rinfo->name, rinfo->version, uuid, tmpAddr);
}
return;
}
-#if !defined(__arm__) && !defined(__arm64__)
/*******************************************************************************
* substitute() looks at an input string (a pointer within a larger buffer)
* for a match to a substring, and on match it writes the marker & substitution
@@ -16026,7 +11639,7 @@
char marker,
char substitution)
{
- size_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1);
+ uint32_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1);
/* On a substring match, append the marker (if there is one) and then
* the substitution character, updating the output (to) index accordingly.
@@ -16115,7 +11728,6 @@
return;
}
-#endif /* !defined(__arm__) && !defined(__arm64__) */
/*******************************************************************************
* assemble_identifier_and_version() adds to a string buffer a compacted
@@ -16124,27 +11736,23 @@
/* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
*/
-static size_t assemble_identifier_and_version(
+static int assemble_identifier_and_version(
kmod_info_t * kmod_info,
char * identPlusVers,
- size_t bufSize);
-
-static size_t
+ int bufSize);
+
+static int
assemble_identifier_and_version(
kmod_info_t * kmod_info,
char * identPlusVers,
- size_t bufSize)
-{
- size_t result = 0;
-
-#if defined(__arm__) || defined(__arm64__)
- result = strlcpy(identPlusVers, kmod_info->name, KMOD_MAX_NAME);
-#else
+ int bufSize)
+{
+ int result = 0;
+
compactIdentifier(kmod_info->name, identPlusVers, NULL);
result = strnlen(identPlusVers, KMOD_MAX_NAME - 1);
-#endif
- identPlusVers[result++] = '\t'; // increment for real char
- identPlusVers[result] = '\0'; // don't increment for nul char
+ identPlusVers[result++] = '\t'; // increment for real char
+ identPlusVers[result] = '\0'; // don't increment for nul char
result = strlcat(identPlusVers, kmod_info->version, bufSize);
if (result >= bufSize) {
identPlusVers[bufSize - 1] = '\0';
@@ -16179,8 +11787,8 @@
OSObject * rawKext = sLoadedKexts->getObject(i);
OSKext * theKext = OSDynamicCast(OSKext, rawKext);
int match;
- size_t identPlusVersLength;
- size_t tempLen;
+ uint32_t identPlusVersLength;
+ uint32_t tempLen;
char identPlusVers[2 * KMOD_MAX_NAME];
if (!rawKext) {
@@ -16266,8 +11874,7 @@
uint32_t newlist_size = 0;
newlist_size = KEXT_PANICLIST_SIZE;
- newlist = (char *)kalloc_data_tag(newlist_size,
- Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
+ newlist = (char *)kalloc_tag(newlist_size, VM_KERN_MEMORY_OSKEXT);
if (!newlist) {
OSKextLog(/* kext */ NULL,
@@ -16295,7 +11902,7 @@
}
if (loaded_kext_paniclist) {
- kfree_data(loaded_kext_paniclist, loaded_kext_paniclist_size);
+ kfree(loaded_kext_paniclist, loaded_kext_paniclist_size);
}
loaded_kext_paniclist = newlist;
newlist = NULL;
@@ -16303,7 +11910,7 @@
finish:
if (newlist) {
- kfree_data(newlist, newlist_size);
+ kfree(newlist, newlist_size);
}
return;
}
@@ -16317,7 +11924,7 @@
u_long len;
if (!kmod_info) {
- return; // do not goto finish here b/c of lock
+ return; // do not goto finish here b/c of lock
}
len = assemble_identifier_and_version( kmod_info,
@@ -16351,36 +11958,28 @@
OSKext::printKextPanicLists(int (*printf_func)(const char *fmt, ...))
{
if (last_loaded_strlen) {
- printf_func("last started kext at %llu: %.*s (addr %p, size %lu)\n",
+ printf_func("last loaded kext at %llu: %.*s (addr %p, size %lu)\n",
AbsoluteTime_to_scalar(&last_loaded_timestamp),
last_loaded_strlen, last_loaded_str_buf,
last_loaded_address, last_loaded_size);
}
if (last_unloaded_strlen) {
- printf_func("last stopped kext at %llu: %.*s (addr %p, size %lu)\n",
+ printf_func("last unloaded kext at %llu: %.*s (addr %p, size %lu)\n",
AbsoluteTime_to_scalar(&last_unloaded_timestamp),
last_unloaded_strlen, last_unloaded_str_buf,
last_unloaded_address, last_unloaded_size);
}
- /*
- * In most cases the set of loaded kexts is statically determined by the
- * Boot KC, so it isn't very interesting to see in the paniclog.
- */
- if (auxKCloaded) {
- printf_func("loaded kexts:\n");
- if (loaded_kext_paniclist &&
- pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) &&
- loaded_kext_paniclist[0]) {
- printf_func("%.*s",
- strnlen(loaded_kext_paniclist, loaded_kext_paniclist_size),
- loaded_kext_paniclist);
- } else {
- printf_func("(none)\n");
- }
+ printf_func("loaded kexts:\n");
+ if (loaded_kext_paniclist &&
+ pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) &&
+ loaded_kext_paniclist[0]) {
+ printf_func("%.*s",
+ strnlen(loaded_kext_paniclist, loaded_kext_paniclist_size),
+ loaded_kext_paniclist);
} else {
- printf_func("loaded kexts: (skipped, see boot kernelcache)\n");
+ printf_func("(none)\n");
}
return;
}
@@ -16396,7 +11995,7 @@
OSKextLoadedKextSummaryHeader *summaryHeader = NULL;
OSKextLoadedKextSummaryHeader *summaryHeaderAlloc = NULL;
OSKext *aKext;
- vm_map_offset_t start;
+ vm_map_offset_t start, end;
size_t summarySize = 0;
size_t size;
u_int count;
@@ -16420,7 +12019,7 @@
count = sLoadedKexts->getCount();
for (i = 0, maxKexts = 0; i < count; ++i) {
aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
- maxKexts += (aKext && (aKext->isExecutable() || aKext->isSpecialKernelBinary()));
+ maxKexts += (aKext && aKext->isExecutable());
}
if (!maxKexts) {
@@ -16444,8 +12043,7 @@
gLoadedKextSummariesTimestamp = mach_absolute_time();
sLoadedKextSummariesAllocSize = 0;
}
- result = kmem_alloc(kernel_map, (vm_offset_t *)&summaryHeaderAlloc, size,
- KMA_NONE, VM_KERN_MEMORY_OSKEXT);
+ result = kmem_alloc(kernel_map, (vm_offset_t *)&summaryHeaderAlloc, size, VM_KERN_MEMORY_OSKEXT);
if (result != KERN_SUCCESS) {
goto finish;
}
@@ -16456,11 +12054,12 @@
summarySize = sLoadedKextSummariesAllocSize;
start = (vm_map_offset_t) summaryHeader;
- result = mach_vm_protect(kernel_map,
+ end = start + summarySize;
+ result = vm_map_protect(kernel_map,
start,
- summarySize,
- false,
- VM_PROT_DEFAULT);
+ end,
+ VM_PROT_DEFAULT,
+ FALSE);
if (result != KERN_SUCCESS) {
goto finish;
}
@@ -16480,7 +12079,7 @@
accountingListAlloc = 0;
for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
- if (!aKext || (!aKext->isExecutable() && !aKext->isSpecialKernelBinary())) {
+ if (!aKext || !aKext->isExecutable()) {
continue;
}
@@ -16493,7 +12092,7 @@
accountingListCount = 0;
for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
- if (!aKext || (!aKext->isExecutable() && !aKext->isSpecialKernelBinary())) {
+ if (!aKext || !aKext->isExecutable()) {
continue;
}
@@ -16514,8 +12113,9 @@
*/
start = (vm_map_offset_t) summaryHeader;
-
- result = mach_vm_protect(kernel_map, start, summarySize, false, VM_PROT_READ);
+ end = start + summarySize;
+
+ result = vm_map_protect(kernel_map, start, end, VM_PROT_READ, FALSE);
if (result != KERN_SUCCESS) {
goto finish;
}
@@ -16532,12 +12132,12 @@
(*sLoadedKextSummariesUpdated)();
}
- lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
+ IOSimpleLockLock(sKextAccountsLock);
prevAccountingList = sKextAccounts;
prevAccountingListCount = sKextAccountsCount;
sKextAccounts = accountingList;
sKextAccountsCount = accountingListCount;
- lck_ticket_unlock(sKextAccountsLock);
+ IOSimpleLockUnlock(sKextAccountsLock);
finish:
IOLockUnlock(sKextSummariesLock);
@@ -16560,7 +12160,7 @@
void
OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary *summary)
{
- OSSharedPtr<OSData> uuid;
+ OSData *uuid;
strlcpy(summary->name, getIdentifierCString(),
sizeof(summary->name));
@@ -16568,6 +12168,7 @@
uuid = copyUUID();
if (uuid) {
memcpy(summary->uuid, uuid->getBytesNoCopy(), sizeof(summary->uuid));
+ OSSafeReleaseNULL(uuid);
}
if (flags.builtin) {
@@ -16585,21 +12186,6 @@
summary->flags = 0;
summary->reference_list = (uint64_t) kmod_info->reference_list;
- summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT_EXEC", &summary->text_exec_size);
- if (summary->text_exec_address == 0) {
- // Fallback to __TEXT
- summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT", &summary->text_exec_size);
- }
-
- /**
- * If the addresses within the Mach-O are unslid, then manually slide any
- * addresses coming from the Mach-O as higher layer software using these
- * summaries expects a slid address here.
- */
- if (flags.unslidMachO) {
- summary->text_exec_address = (uint64_t) ml_static_slide((vm_offset_t) summary->text_exec_address);
- }
-
return;
}
@@ -16615,10 +12201,8 @@
bzero(accountp, sizeof(*accountp));
hdr = (kernel_mach_header_t *)kmod_info->address;
- if (getcommandfromheader(hdr, LC_SEGMENT_SPLIT_INFO) || isInFileset()) {
- /*
- * If this kext supports split segments (or is in a new
- * MH_FILESET kext collection), use the first
+ if (getcommandfromheader(hdr, LC_SEGMENT_SPLIT_INFO)) {
+ /* If this kext supports split segments, use the first
* executable segment as the range for instructions
* (and thus for backtracing.
*/
@@ -16662,114 +12246,6 @@
return FALSE;
}
-bool
-OSKext::isInFileset(void)
-{
- if (!kmod_info) {
- goto check_prelinked;
- }
-
- if (kmod_info->address && kernel_mach_header_is_in_fileset((kernel_mach_header_t *)kmod_info->address)) {
- return true;
- }
-
-check_prelinked:
- if (isPrelinked()) {
- /*
- * If we haven't setup kmod_info yet, but we know
- * we're loading a prelinked kext in an MH_FILESET KC,
- * then return true
- */
- kc_format_t kc_format;
- if (PE_get_primary_kc_format(&kc_format) && kc_format == KCFormatFileset) {
- return true;
- }
- }
- return false;
-}
-
-OSSharedPtr<OSDextStatistics>
-OSKext::copyDextStatistics(void)
-{
- return dextStatistics;
-}
-
-bool
-OSKextSavedMutableSegment::initWithSegment(kernel_segment_command_t *seg)
-{
- kern_return_t result;
- if (!super::init()) {
- return false;
- }
- if (seg == nullptr) {
- return false;
- }
- result = kmem_alloc(kernel_map, (vm_offset_t *)&data, seg->vmsize,
- KMA_PAGEABLE, VM_KERN_MEMORY_KEXT);
- if (result != KERN_SUCCESS) {
- return false;
- }
- memcpy((void *)data, (const void *)seg->vmaddr, seg->vmsize);
- savedSegment = seg;
- vmsize = seg->vmsize;
- vmaddr = seg->vmaddr;
- return true;
-}
-
-OSSharedPtr<OSKextSavedMutableSegment>
-OSKextSavedMutableSegment::withSegment(kernel_segment_command_t *seg)
-{
- OSSharedPtr<OSKextSavedMutableSegment> me = OSMakeShared<OSKextSavedMutableSegment>();
- if (me && !me->initWithSegment(seg)) {
- return nullptr;
- }
- return me;
-}
-
-void
-OSKextSavedMutableSegment::free(void)
-{
- if (data) {
- kmem_free(kernel_map, (vm_offset_t)data, vmsize);
- }
-}
-
-vm_offset_t
-OSKextSavedMutableSegment::getVMAddr() const
-{
- return vmaddr;
-}
-
-vm_offset_t
-OSKextSavedMutableSegment::getVMSize() const
-{
- return vmsize;
-}
-
-OSReturn
-OSKextSavedMutableSegment::restoreContents(kernel_segment_command_t *seg)
-{
- if (seg != savedSegment) {
- return kOSKextReturnInvalidArgument;
- }
- if (seg->vmaddr != vmaddr || seg->vmsize != vmsize) {
- return kOSKextReturnInvalidArgument;
- }
- memcpy((void *)seg->vmaddr, data, vmsize);
- return kOSReturnSuccess;
-}
-
-extern "C" kern_return_t
-OSKextSetReceiptQueried(void)
-{
- OSKextLog(/* kext */ NULL,
- kOSKextLogStepLevel | kOSKextLogGeneralFlag,
- "Setting kext receipt as queried");
-
- IOService::publishResource(kOSKextReceiptQueried, kOSBooleanTrue);
- return KERN_SUCCESS;
-}
-
extern "C" const vm_allocation_site_t *
OSKextGetAllocationSiteForCaller(uintptr_t address)
{
@@ -16779,11 +12255,8 @@
uint32_t baseIdx;
uint32_t lim;
-#if __has_feature(ptrauth_calls)
- address = (uintptr_t)VM_KERNEL_STRIP_PTR(address);
-#endif /* __has_feature(ptrauth_calls) */
-
- lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
+
+ IOSimpleLockLock(sKextAccountsLock);
site = releasesite = NULL;
// bsearch sKextAccounts list
@@ -16802,44 +12275,13 @@
}
// else move left
}
- lck_ticket_unlock(sKextAccountsLock);
+ IOSimpleLockUnlock(sKextAccountsLock);
if (releasesite) {
kern_allocation_name_release(releasesite);
}
return site;
}
-
-#if DEVELOPMENT || DEBUG
-extern "C" void
-OSKextGetRefGrpForCaller(uintptr_t address, void (^cb)(struct os_refgrp *))
-{
- OSKextActiveAccount * active;
-
- uint32_t baseIdx;
- uint32_t lim;
-#if __has_feature(ptrauth_calls)
- address = (uintptr_t)VM_KERNEL_STRIP_PTR(address);
-#endif /* __has_feature(ptrauth_calls) */
-
- lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
-
- // bsearch sKextAccounts list
- for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
- active = &sKextAccounts[baseIdx + (lim >> 1)];
- if ((address >= active->address) && (address < active->address_end)) {
- cb(&active->account->task_refgrp);
- break;
- } else if (address > active->address) {
- // move right
- baseIdx += (lim >> 1) + 1;
- lim--;
- }
- // else move left
- }
- lck_ticket_unlock(sKextAccountsLock);
-}
-#endif /* DEVELOPMENT || DEBUG */
extern "C" uint32_t
OSKextGetKmodIDForSite(const vm_allocation_site_t * site, char * name, vm_size_t namelen)
@@ -16863,7 +12305,7 @@
OSKextFreeSite(vm_allocation_site_t * site)
{
OSKextAccount * freeAccount = (typeof(freeAccount))site;
- IOFreeType(freeAccount, OSKextAccount);
+ IODelete(freeAccount, OSKextAccount, 1);
}
/*********************************************************************
@@ -16873,154 +12315,18 @@
int
OSKextGetUUIDForName(const char *name, uuid_t uuid)
{
- OSSharedPtr<OSKext> kext = OSKext::lookupKextWithIdentifier(name);
+ OSKext *kext = OSKext::lookupKextWithIdentifier(name);
if (!kext) {
return 1;
}
- OSSharedPtr<OSData> uuid_data = kext->copyUUID();
+ OSData *uuid_data = kext->copyUUID();
if (uuid_data) {
memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_t));
+ OSSafeReleaseNULL(uuid_data);
return 0;
}
return 1;
}
#endif
-
-
-
-class OSDextCrash : public OSObject {
- OSDeclareDefaultStructors(OSDextCrash);
-public:
- static OSPtr<OSDextCrash> withTimestamp(uint64_t timestamp);
- uint64_t getTimestamp();
-
-private:
- virtual bool initWithTimestamp(uint64_t timestamp);
- uint64_t fTimestamp;
-};
-
-OSDefineMetaClassAndStructors(OSDextCrash, OSObject);
-
-OSSharedPtr<OSDextCrash>
-OSDextCrash::withTimestamp(uint64_t timestamp)
-{
- OSSharedPtr<OSDextCrash> result = OSMakeShared<OSDextCrash>();
- if (!result->initWithTimestamp(timestamp)) {
- return NULL;
- }
- return result;
-}
-
-bool
-OSDextCrash::initWithTimestamp(uint64_t timestamp)
-{
- if (!OSObject::init()) {
- return false;
- }
- fTimestamp = timestamp;
- return true;
-}
-
-uint64_t
-OSDextCrash::getTimestamp()
-{
- return fTimestamp;
-}
-
-OSSharedPtr<OSDextStatistics>
-OSDextStatistics::create()
-{
- OSSharedPtr<OSDextStatistics> result = OSMakeShared<OSDextStatistics>();
- if (!result->init()) {
- return NULL;
- }
- return result;
-}
-
-bool
-OSDextStatistics::init()
-{
- if (!OSObject::init()) {
- return false;
- }
-
- lock = IOLockAlloc();
- crashes = OSArray::withCapacity(kMaxDextCrashesInOneDay);
- return true;
-}
-
-void
-OSDextStatistics::free()
-{
- if (lock) {
- IOLockFree(lock);
- }
- crashes.reset();
- OSObject::free();
-}
-
-OSDextCrashPolicy
-OSDextStatistics::recordCrash()
-{
- size_t i = 0;
- uint64_t timestamp = mach_continuous_time();
- uint64_t interval;
- nanoseconds_to_absolutetime(86400 * NSEC_PER_SEC /* 1 day */, &interval);
- uint64_t lastTimestamp = timestamp > interval ? timestamp - interval : 0;
- OSDextCrashPolicy policy;
-
- IOLockLock(lock);
- OSSharedPtr<OSDextCrash> crash = OSDextCrash::withTimestamp(timestamp);
- for (i = 0; i < crashes->getCount();) {
- OSDextCrash * current = OSDynamicCast(OSDextCrash, crashes->getObject(i));
- assert(current != NULL);
- if (current->getTimestamp() < lastTimestamp) {
- crashes->removeObject(i);
- } else {
- i++;
- }
- }
-
- crashes->setObject(crash);
-
- if (crashes->getCount() > kMaxDextCrashesInOneDay) {
- policy = kOSDextCrashPolicyReboot;
- } else {
- policy = kOSDextCrashPolicyNone;
- }
-
- IOLockUnlock(lock);
-
- return policy;
-}
-
-size_t
-OSDextStatistics::getCrashCount()
-{
- size_t result = 0;
- IOLockLock(lock);
- result = crashes->getCount();
- IOLockUnlock(lock);
- return result;
-}
-
-static int
-sysctl_willuserspacereboot
-(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
-{
- int new_value = 0, old_value = get_system_inuserspacereboot(), changed = 0;
- int error = sysctl_io_number(req, old_value, sizeof(int), &new_value, &changed);
- if (error) {
- return error;
- }
- if (changed) {
- OSKext::setWillUserspaceReboot();
- }
- return 0;
-}
-
-static SYSCTL_PROC(_kern, OID_AUTO, willuserspacereboot,
- CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
- NULL, 0, sysctl_willuserspacereboot, "I", "");