Loading...
libsa/bootstrap.cpp xnu-12377.101.15 xnu-6153.11.26
--- xnu/xnu-12377.101.15/libsa/bootstrap.cpp
+++ xnu/xnu-6153.11.26/libsa/bootstrap.cpp
@@ -29,10 +29,7 @@
 #include <mach/kmod.h>
 #include <libkern/kernel_mach_header.h>
 #include <libkern/prelink.h>
-#include <libkern/crypto/sha2.h>
-}
-
-#define IOKIT_ENABLE_SHARED_PTR
+}
 
 #include <libkern/version.h>
 #include <libkern/c++/OSContainers.h>
@@ -104,7 +101,6 @@
 	"com.apple.kpi.dsep",
 	"com.apple.kpi.iokit",
 	"com.apple.kpi.kasan",
-	"com.apple.kpi.kcov",
 	"com.apple.kpi.libkern",
 	"com.apple.kpi.mach",
 	"com.apple.kpi.private",
@@ -116,6 +112,26 @@
 	NULL
 };
 
+static int __whereIsAddr(vm_offset_t theAddr, unsigned long * segSizes, vm_offset_t *segAddrs, int segCount );
+
+#define PLK_SEGMENTS 12
+
+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",
+	NULL
+};
+
 #if PRAGMA_MARK
 #pragma mark KLDBootstrap Class
 #endif
@@ -133,7 +149,8 @@
 private:
 	void readStartupExtensions(void);
 
-	void readPrelinkedExtensions(kernel_mach_header_t *mh, kc_kind_t type);
+	void readPrelinkedExtensions(
+		kernel_section_t * prelinkInfoSect);
 	void readBooterExtensions(void);
 
 	OSReturn loadKernelComponentKexts(void);
@@ -190,69 +207,147 @@
 	    kOSKextLogKextBookkeepingFlag,
 	    "Reading startup extensions.");
 
-	kc_format_t kc_format;
-	kernel_mach_header_t *mh = &_mh_execute_header;
-	if (PE_get_primary_kc_format(&kc_format) && kc_format == KCFormatFileset) {
-		mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary);
-	}
-
 	/* If the prelink info segment has a nonzero size, we are prelinked
 	 * and won't have any individual kexts or mkexts to read.
 	 * Otherwise, we need to read kexts or the mkext from what the booter
 	 * has handed us.
 	 */
-	prelinkInfoSect = getsectbynamefromheader(mh, kPrelinkInfoSegment, kPrelinkInfoSection);
+	prelinkInfoSect = getsectbyname(kPrelinkInfoSegment, kPrelinkInfoSection);
 	if (prelinkInfoSect->size) {
-		readPrelinkedExtensions(mh, KCKindPrimary);
+		readPrelinkedExtensions(prelinkInfoSect);
 	} else {
 		readBooterExtensions();
-	}
-
-	kernel_mach_header_t *akc_mh;
-	akc_mh = (kernel_mach_header_t*)PE_get_kc_header(KCKindAuxiliary);
-	if (akc_mh) {
-		readPrelinkedExtensions(akc_mh, KCKindAuxiliary);
 	}
 
 	loadKernelComponentKexts();
 	loadKernelExternalComponents();
 	readBuiltinPersonalities();
-	OSKext::sendAllKextPersonalitiesToCatalog(true);
+	OSKext::sendAllKextPersonalitiesToCatalog();
 
 	return;
 }
 
+typedef struct kaslrPackedOffsets {
+	uint32_t    count;          /* number of offsets */
+	uint32_t    offsetsArray[]; /* offsets to slide */
+} kaslrPackedOffsets;
+
 /*********************************************************************
 *********************************************************************/
 void
-KLDBootstrap::readPrelinkedExtensions(kernel_mach_header_t *mh, kc_kind_t type)
-{
-	bool ret;
-	OSSharedPtr<OSData> loaded_kcUUID;
-	OSSharedPtr<OSString> errorString;
-	OSSharedPtr<OSObject> parsedXML;
-	kernel_section_t *infoPlistSection = NULL;
-	OSDictionary *infoDict = NULL;         // do not release
+KLDBootstrap::readPrelinkedExtensions(
+	kernel_section_t * prelinkInfoSect)
+{
+	OSArray                   * infoDictArray           = NULL;// do not release
+	OSObject                  * parsedXML       = NULL;// must release
+	OSDictionary              * prelinkInfoDict         = NULL;// do not release
+	OSString                  * errorString             = NULL;// must release
+	OSKext                    * theKernel               = NULL;// must release
+	OSData                    * kernelcacheUUID         = NULL;// do not release
+
+	kernel_segment_command_t  * prelinkTextSegment      = NULL;// see code
+	kernel_segment_command_t  * prelinkInfoSegment      = NULL;// see code
+
+	/* We make some copies of data, but if anything fails we're basically
+	 * going to fail the boot, so these won't be cleaned up on error.
+	 */
+	void                      * prelinkData             = NULL;// see code
+	vm_size_t                   prelinkLength           = 0;
+
+
+	OSDictionary              * infoDict                = NULL;// do not release
+
+	IORegistryEntry           * registryRoot            = NULL;// do not release
+	OSNumber                  * prelinkCountObj         = NULL;// must release
+
+	u_int                       i = 0;
+#if NO_KEXTD
+	bool                        ramDiskBoot;
+	bool                        developerDevice;
+	bool                        dontLoad;
+#endif
+	OSData                     * kaslrOffsets = NULL;
+	unsigned long               plk_segSizes[PLK_SEGMENTS];
+	vm_offset_t                 plk_segAddrs[PLK_SEGMENTS];
 
 	OSKextLog(/* kext */ NULL,
 	    kOSKextLogProgressLevel |
 	    kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
 	    "Starting from prelinked kernel.");
 
-	/*
-	 * The 'infoPlistSection' should contains an XML dictionary that
-	 * contains some meta data about the KC, and also describes each kext
-	 * included in the kext collection. Unserialize this dictionary and
-	 * then iterate over each kext.
+	prelinkTextSegment = getsegbyname(kPrelinkTextSegment);
+	if (!prelinkTextSegment) {
+		OSKextLog(/* kext */ NULL,
+		    kOSKextLogErrorLevel |
+		    kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
+		    "Can't find prelinked kexts' text segment.");
+		goto finish;
+	}
+
+#if KASLR_KEXT_DEBUG
+	unsigned long   scratchSize;
+	vm_offset_t     scratchAddr;
+
+	IOLog("kaslr: prelinked kernel address info: \n");
+
+	scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__TEXT", &scratchSize);
+	IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __TEXT \n",
+	    (unsigned long)scratchAddr,
+	    (unsigned long)(scratchAddr + scratchSize),
+	    scratchSize);
+
+	scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__DATA", &scratchSize);
+	IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __DATA \n",
+	    (unsigned long)scratchAddr,
+	    (unsigned long)(scratchAddr + scratchSize),
+	    scratchSize);
+
+	scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__LINKEDIT", &scratchSize);
+	IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __LINKEDIT \n",
+	    (unsigned long)scratchAddr,
+	    (unsigned long)(scratchAddr + scratchSize),
+	    scratchSize);
+
+	scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__KLD", &scratchSize);
+	IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __KLD \n",
+	    (unsigned long)scratchAddr,
+	    (unsigned long)(scratchAddr + scratchSize),
+	    scratchSize);
+
+	scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__PRELINK_TEXT", &scratchSize);
+	IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __PRELINK_TEXT \n",
+	    (unsigned long)scratchAddr,
+	    (unsigned long)(scratchAddr + scratchSize),
+	    scratchSize);
+
+	scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__PRELINK_INFO", &scratchSize);
+	IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __PRELINK_INFO \n",
+	    (unsigned long)scratchAddr,
+	    (unsigned long)(scratchAddr + scratchSize),
+	    scratchSize);
+#endif
+
+	prelinkData = (void *) prelinkTextSegment->vmaddr;
+	prelinkLength = prelinkTextSegment->vmsize;
+
+	/* build arrays of plk info for later use */
+	const char ** segNamePtr;
+
+	for (segNamePtr = &plk_segNames[0], i = 0; *segNamePtr && i < PLK_SEGMENTS; segNamePtr++, i++) {
+		plk_segSizes[i] = 0;
+		plk_segAddrs[i] = (vm_offset_t)getsegdatafromheader(&_mh_execute_header, *segNamePtr, &plk_segSizes[i]);
+	}
+
+
+	/* Unserialize the info dictionary from the prelink info section.
 	 */
-	infoPlistSection = getsectbynamefromheader(mh, kPrelinkInfoSegment, kPrelinkInfoSection);
-	parsedXML = OSUnserializeXML((const char *)infoPlistSection->addr, errorString);
+	parsedXML = OSUnserializeXML((const char *)prelinkInfoSect->addr,
+	    &errorString);
 	if (parsedXML) {
-		infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
-	}
-
-	if (!infoDict) {
-		const char *errorCString = "(unknown error)";
+		prelinkInfoDict = OSDynamicCast(OSDictionary, parsedXML);
+	}
+	if (!prelinkInfoDict) {
+		const char * errorCString = "(unknown error)";
 
 		if (errorString && errorString->getCStringNoCopy()) {
 			errorCString = errorString->getCStringNoCopy();
@@ -260,105 +355,216 @@
 			errorCString = "not a dictionary";
 		}
 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
-		    "Error unserializing kext info plist section: %s.", errorCString);
-		return;
-	}
-
-	/* Validate that the Kext Collection is prelinked to the loaded KC */
-	if (type == KCKindAuxiliary) {
-		if (OSKext::validateKCFileSetUUID(infoDict, KCKindAuxiliary) != 0) {
-			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
-			    "Early boot AuxKC  doesn't appear to be linked against the loaded BootKC.");
-			return;
-		}
-
-		/*
-		 * Defer further processing of the AuxKC, but keep the
-		 * processed info dictionary around so we can ml_static_free
-		 * the segment.
+		    "Error unserializing prelink plist: %s.", errorCString);
+		goto finish;
+	}
+
+#if NO_KEXTD
+	/* Check if we should keep developer kexts around.
+	 * TODO: Check DeviceTree instead of a boot-arg <rdar://problem/10604201>
+	 */
+	developerDevice = true;
+	PE_parse_boot_argn("developer", &developerDevice, sizeof(developerDevice));
+
+	ramDiskBoot = IORamDiskBSDRoot();
+#endif /* NO_KEXTD */
+
+	/* Copy in the kernelcache UUID */
+	kernelcacheUUID = OSDynamicCast(OSData,
+	    prelinkInfoDict->getObject(kPrelinkInfoKCIDKey));
+	if (kernelcacheUUID) {
+		if (kernelcacheUUID->getLength() != sizeof(kernelcache_uuid)) {
+			panic("kernelcacheUUID length is %d, expected %lu", kernelcacheUUID->getLength(),
+			    sizeof(kernelcache_uuid));
+		} else {
+			kernelcache_uuid_valid = TRUE;
+			memcpy((void *)&kernelcache_uuid, (const void *)kernelcacheUUID->getBytesNoCopy(), kernelcacheUUID->getLength());
+			uuid_unparse_upper(kernelcache_uuid, kernelcache_uuid_string);
+		}
+	}
+
+	infoDictArray = OSDynamicCast(OSArray,
+	    prelinkInfoDict->getObject(kPrelinkInfoDictionaryKey));
+	if (!infoDictArray) {
+		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
+		    "The prelinked kernel has no kext info dictionaries");
+		goto finish;
+	}
+
+	/* kaslrOffsets are available use them to slide local relocations */
+	kaslrOffsets = OSDynamicCast(OSData,
+	    prelinkInfoDict->getObject(kPrelinkLinkKASLROffsetsKey));
+
+	/* Create dictionary of excluded kexts
+	 */
+#ifndef CONFIG_EMBEDDED
+	OSKext::createExcludeListFromPrelinkInfo(infoDictArray);
+#endif
+	/* Create OSKext objects for each info dictionary.
+	 */
+	for (i = 0; i < infoDictArray->getCount(); ++i) {
+		infoDict = OSDynamicCast(OSDictionary, infoDictArray->getObject(i));
+		if (!infoDict) {
+			OSKextLog(/* kext */ NULL,
+			    kOSKextLogErrorLevel |
+			    kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
+			    "Can't find info dictionary for prelinked kext #%d.", i);
+			continue;
+		}
+
+#if NO_KEXTD
+		dontLoad = false;
+
+		/* If we're not on a developer device, skip and free developer kexts.
 		 */
-		if (!OSKext::registerDeferredKextCollection(mh, parsedXML, KCKindAuxiliary)) {
-			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
-			    "Error deferring AuxKC kext processing: Kexts in this collection will be unusable.");
-		}
-		goto skip_adding_kexts;
-	}
-
-	/*
-	 * this function does all the heavy lifting of adding OSKext objects
-	 * and potentially sliding them if necessary
+		if (developerDevice == false) {
+			OSBoolean *devOnlyBool = OSDynamicCast(OSBoolean,
+			    infoDict->getObject(kOSBundleDeveloperOnlyKey));
+			if (devOnlyBool == kOSBooleanTrue) {
+				dontLoad = true;
+			}
+		}
+
+		/* Skip and free kexts that are only needed when booted from a ram disk.
+		 */
+		if (ramDiskBoot == false) {
+			OSBoolean *ramDiskOnlyBool = OSDynamicCast(OSBoolean,
+			    infoDict->getObject(kOSBundleRamDiskOnlyKey));
+			if (ramDiskOnlyBool == kOSBooleanTrue) {
+				dontLoad = true;
+			}
+		}
+
+		if (dontLoad == true) {
+			OSString *bundleID = OSDynamicCast(OSString,
+			    infoDict->getObject(kCFBundleIdentifierKey));
+			if (bundleID) {
+				OSKextLog(NULL, kOSKextLogWarningLevel | kOSKextLogGeneralFlag,
+				    "Kext %s not loading.", bundleID->getCStringNoCopy());
+			}
+
+			OSNumber *addressNum = OSDynamicCast(OSNumber,
+			    infoDict->getObject(kPrelinkExecutableLoadKey));
+			OSNumber *lengthNum = OSDynamicCast(OSNumber,
+			    infoDict->getObject(kPrelinkExecutableSizeKey));
+			if (addressNum && lengthNum) {
+#if __arm__ || __arm64__
+				vm_offset_t data = ml_static_slide(addressNum->unsigned64BitValue());
+				vm_size_t length = (vm_size_t) (lengthNum->unsigned32BitValue());
+				ml_static_mfree(data, length);
+#else
+#error Pick the right way to free prelinked data on this arch
+#endif
+			}
+
+			infoDictArray->removeObject(i--);
+			continue;
+		}
+#endif /* NO_KEXTD */
+
+		/* Create the kext for the entry, then release it, because the
+		 * kext system keeps them around until explicitly removed.
+		 * Any creation/registration failures are already logged for us.
+		 */
+		OSKext * newKext = OSKext::withPrelinkedInfoDict(infoDict, (kaslrOffsets ? TRUE : FALSE));
+		OSSafeReleaseNULL(newKext);
+	}
+
+	/* slide kxld relocations */
+	if (kaslrOffsets && vm_kernel_slide > 0) {
+		int slidKextAddrCount = 0;
+		int badSlideAddr = 0;
+		int badSlideTarget = 0;
+
+		const kaslrPackedOffsets * myOffsets = NULL;
+		myOffsets = (const kaslrPackedOffsets *) kaslrOffsets->getBytesNoCopy();
+
+		for (uint32_t j = 0; j < myOffsets->count; j++) {
+			uint64_t        slideOffset = (uint64_t) myOffsets->offsetsArray[j];
+			uintptr_t *     slideAddr = (uintptr_t *) ((uint64_t)prelinkData + slideOffset);
+			int             slideAddrSegIndex = -1;
+			int             addrToSlideSegIndex = -1;
+
+			slideAddrSegIndex = __whereIsAddr((vm_offset_t)slideAddr, &plk_segSizes[0], &plk_segAddrs[0], PLK_SEGMENTS );
+			if (slideAddrSegIndex >= 0) {
+				addrToSlideSegIndex = __whereIsAddr(ml_static_slide((vm_offset_t)(*slideAddr)), &plk_segSizes[0], &plk_segAddrs[0], PLK_SEGMENTS );
+				if (addrToSlideSegIndex < 0) {
+					badSlideTarget++;
+					continue;
+				}
+			} else {
+				badSlideAddr++;
+				continue;
+			}
+
+			slidKextAddrCount++;
+			*slideAddr = ml_static_slide(*slideAddr);
+		} // for ...
+
+		/* All kexts are now slid, set VM protections for them */
+		OSKext::setAllVMAttributes();
+	}
+
+	/* Store the number of prelinked kexts in the registry so we can tell
+	 * when the system has been started from a prelinked kernel.
 	 */
-	ret = OSKext::addKextsFromKextCollection(mh, infoDict,
-	    kPrelinkTextSegment, loaded_kcUUID, (mh->filetype == MH_FILESET) ? type : KCKindUnknown);
-
-	if (!ret) {
-		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
-		    "Error loading kext info from prelinked primary KC");
-		return;
-	}
-
-	/* Copy in the kernelcache UUID */
-	if (!loaded_kcUUID) {
-		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
-		    "WARNING: did not find UUID in %s KC!", (type == KCKindAuxiliary) ? "Aux" : "Primary");
-	} else if (type != KCKindAuxiliary) {
-		kernelcache_uuid_valid = TRUE;
-		memcpy((void *)&kernelcache_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
-		uuid_unparse_upper(kernelcache_uuid, kernelcache_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);
-	}
-
-skip_adding_kexts:
+	registryRoot = IORegistryEntry::getRegistryRoot();
+	assert(registryRoot);
+
+	prelinkCountObj = OSNumber::withNumber(
+		(unsigned long long)infoDictArray->getCount(),
+		8 * sizeof(uint32_t));
+	assert(prelinkCountObj);
+	if (prelinkCountObj) {
+		registryRoot->setProperty(kOSPrelinkKextCountKey, prelinkCountObj);
+	}
+
+	OSKextLog(/* kext */ NULL,
+	    kOSKextLogProgressLevel |
+	    kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag |
+	    kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
+	    "%u prelinked kexts",
+	    infoDictArray->getCount());
+
 #if CONFIG_KEXT_BASEMENT
-	if (mh->filetype != MH_FILESET) {
-		/*
-		 * On CONFIG_KEXT_BASEMENT systems which do _not_ boot the new
-		 * MH_FILESET kext collection, kexts are copied to their own
-		 * special VM region during OSKext init time, so we can free
-		 * the whole segment now.
-		 */
-		kernel_segment_command_t *prelinkTextSegment = NULL;
-		prelinkTextSegment = getsegbyname(kPrelinkTextSegment);
-		if (!prelinkTextSegment) {
-			OSKextLog(/* kext */ NULL,
-			    kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
-			    "Can't find prelinked kexts' text segment.");
-			return;
-		}
-
-		ml_static_mfree((vm_offset_t)prelinkTextSegment->vmaddr, prelinkTextSegment->vmsize);
-	}
-#endif /* CONFIG_KEXT_BASEMENT */
-
-	/*
-	 * Free the prelink info segment, we're done with it.
+	/* On CONFIG_KEXT_BASEMENT systems, kexts are copied to their own
+	 * special VM region during OSKext init time, so we can free the whole
+	 * segment now.
 	 */
-
-#if !XNU_TARGET_OS_OSX
-	/*
-	 * For now, we are limiting this freeing to embedded platforms.
-	 * To enable freeing of prelink info segment on macOS, we need to
-	 * fix rdar://88929016
+	ml_static_mfree((vm_offset_t) prelinkData, prelinkLength);
+#endif /* __x86_64__ */
+
+	/* Free the prelink info segment, we're done with it.
 	 */
-	bool freedPrelinkInfo = false;
-	kernel_segment_command_t *prelinkInfoSegment = NULL;
-	prelinkInfoSegment = getsegbynamefromheader(mh, kPrelinkInfoSegment);
+	prelinkInfoSegment = getsegbyname(kPrelinkInfoSegment);
 	if (prelinkInfoSegment) {
-		if (prelinkInfoSegment->vmsize != 0) {
-			freedPrelinkInfo = true;
-			ml_static_mfree((vm_offset_t)prelinkInfoSegment->vmaddr,
-			    (vm_size_t)prelinkInfoSegment->vmsize);
-		}
-	}
-
-	if (!freedPrelinkInfo) {
-		OSKextLog(NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, "Failed to free prelink info.");
-	}
-#endif
+		ml_static_mfree((vm_offset_t)prelinkInfoSegment->vmaddr,
+		    (vm_size_t)prelinkInfoSegment->vmsize);
+	}
+
+finish:
+	OSSafeReleaseNULL(errorString);
+	OSSafeReleaseNULL(parsedXML);
+	OSSafeReleaseNULL(theKernel);
+	OSSafeReleaseNULL(prelinkCountObj);
 	return;
+}
+
+static int
+__whereIsAddr(vm_offset_t theAddr, unsigned long * segSizes, vm_offset_t *segAddrs, int segCount)
+{
+	int i;
+
+	for (i = 0; i < segCount; i++) {
+		vm_offset_t         myAddr = *(segAddrs + i);
+		unsigned long       mySize = *(segSizes + i);
+
+		if (theAddr >= myAddr && theAddr < (myAddr + mySize)) {
+			return i;
+		}
+	}
+
+	return -1;
 }
 
 
@@ -374,15 +580,16 @@
 void
 KLDBootstrap::readBooterExtensions(void)
 {
-	OSSharedPtr<IORegistryEntry> booterMemoryMap;
-	OSSharedPtr<OSDictionary>    propertyDict;
-	OSSharedPtr<OSCollectionIterator>      keyIterator;
+	IORegistryEntry           * booterMemoryMap         = NULL;// must release
+	OSDictionary              * propertyDict            = NULL;// must release
+	OSCollectionIterator      * keyIterator             = NULL;// must release
 	OSString                  * deviceTreeName          = NULL;// do not release
 
 	const _DeviceTreeBuffer   * deviceTreeBuffer        = NULL;// do not free
 	char                      * booterDataPtr           = NULL;// do not free
-	OSSharedPtr<OSData>         booterData;
-	OSSharedPtr<OSKext>         aKext;
+	OSData                    * booterData              = NULL;// must release
+
+	OSKext                    * aKext                   = NULL;// must release
 
 	OSKextLog(/* kext */ NULL,
 	    kOSKextLogProgressLevel |
@@ -408,7 +615,7 @@
 		goto finish;
 	}
 
-	keyIterator = OSCollectionIterator::withCollection(propertyDict.get());
+	keyIterator = OSCollectionIterator::withCollection(propertyDict);
 	if (!keyIterator) {
 		OSKextLog(/* kext */ NULL,
 		    kOSKextLogErrorLevel |
@@ -420,9 +627,8 @@
 	/* Create dictionary of excluded kexts
 	 */
 #ifndef CONFIG_EMBEDDED
-	OSKext::createExcludeListFromBooterData(propertyDict.get(), keyIterator.get());
-#endif
-	// !! reset the iterator, not the pointer
+	OSKext::createExcludeListFromBooterData(propertyDict, keyIterator);
+#endif
 	keyIterator->reset();
 
 	while ((deviceTreeName =
@@ -430,6 +636,10 @@
 		const char * devTreeNameCString = deviceTreeName->getCStringNoCopy();
 		OSData * deviceTreeEntry = OSDynamicCast(OSData,
 		    propertyDict->getObject(deviceTreeName));
+
+		/* Clear out the booterData from the prior iteration.
+		 */
+		OSSafeReleaseNULL(booterData);
 
 		/* If there is no entry for the name, we can't do much with it. */
 		if (!deviceTreeEntry) {
@@ -488,12 +698,19 @@
 		 * kext system keeps them around until explicitly removed.
 		 * Any creation/registration failures are already logged for us.
 		 */
-		OSSharedPtr<OSKext> newKext = OSKext::withBooterData(deviceTreeName, booterData.get());
+		OSKext * newKext = OSKext::withBooterData(deviceTreeName, booterData);
+		OSSafeReleaseNULL(newKext);
 
 		booterMemoryMap->removeProperty(deviceTreeName);
 	} /* while ( (deviceTreeName = OSDynamicCast(OSString, ...) ) ) */
 
 finish:
+
+	OSSafeReleaseNULL(booterMemoryMap);
+	OSSafeReleaseNULL(propertyDict);
+	OSSafeReleaseNULL(keyIterator);
+	OSSafeReleaseNULL(booterData);
+	OSSafeReleaseNULL(aKext);
 	return;
 }
 
@@ -504,8 +721,8 @@
 void
 KLDBootstrap::loadSecurityExtensions(void)
 {
-	OSSharedPtr<OSDictionary>         extensionsDict;
-	OSSharedPtr<OSCollectionIterator> keyIterator;
+	OSDictionary         * extensionsDict = NULL;// must release
+	OSCollectionIterator * keyIterator    = NULL;// must release
 	OSString             * bundleID       = NULL;// don't release
 	OSKext               * theKext        = NULL;// don't release
 
@@ -519,7 +736,7 @@
 		return;
 	}
 
-	keyIterator = OSCollectionIterator::withCollection(extensionsDict.get());
+	keyIterator = OSCollectionIterator::withCollection(extensionsDict);
 	if (!keyIterator) {
 		OSKextLog(/* kext */ NULL,
 		    kOSKextLogErrorLevel |
@@ -554,6 +771,9 @@
 	}
 
 finish:
+	OSSafeReleaseNULL(keyIterator);
+	OSSafeReleaseNULL(extensionsDict);
+
 	return;
 }
 
@@ -571,11 +791,12 @@
 OSReturn
 KLDBootstrap::loadKernelComponentKexts(void)
 {
-	OSReturn            result      = kOSReturnSuccess;// optimistic
-	OSSharedPtr<OSKext> theKext;
-	const char       ** kextIDPtr   = NULL;          // do not release
+	OSReturn      result      = kOSReturnSuccess;// optimistic
+	OSKext      * theKext     = NULL;          // must release
+	const char ** kextIDPtr   = NULL;          // do not release
 
 	for (kextIDPtr = &sKernelComponentNames[0]; *kextIDPtr; kextIDPtr++) {
+		OSSafeReleaseNULL(theKext);
 		theKext = OSKext::lookupKextWithIdentifier(*kextIDPtr);
 
 		if (theKext) {
@@ -591,6 +812,7 @@
 		}
 	}
 
+	OSSafeReleaseNULL(theKext);
 	return result;
 }
 
@@ -607,8 +829,8 @@
 void
 KLDBootstrap::loadKernelExternalComponents(void)
 {
-	OSSharedPtr<OSDictionary>         extensionsDict;
-	OSSharedPtr<OSCollectionIterator> keyIterator;
+	OSDictionary         * extensionsDict = NULL;// must release
+	OSCollectionIterator * keyIterator    = NULL;// must release
 	OSString             * bundleID       = NULL;// don't release
 	OSKext               * theKext        = NULL;// don't release
 	OSBoolean            * isKernelExternalComponent = NULL;// don't release
@@ -623,7 +845,7 @@
 		return;
 	}
 
-	keyIterator = OSCollectionIterator::withCollection(extensionsDict.get());
+	keyIterator = OSCollectionIterator::withCollection(extensionsDict);
 	if (!keyIterator) {
 		OSKextLog(/* kext */ NULL,
 		    kOSKextLogErrorLevel |
@@ -660,6 +882,9 @@
 	}
 
 finish:
+	OSSafeReleaseNULL(keyIterator);
+	OSSafeReleaseNULL(extensionsDict);
+
 	return;
 }
 
@@ -668,12 +893,12 @@
 void
 KLDBootstrap::readBuiltinPersonalities(void)
 {
-	OSSharedPtr<OSObject>   parsedXML;
+	OSObject              * parsedXML             = NULL;// must release
 	OSArray               * builtinExtensions     = NULL;// do not release
-	OSSharedPtr<OSArray>    allPersonalities;
-	OSSharedPtr<OSString>   errorString;
+	OSArray               * allPersonalities      = NULL;// must release
+	OSString              * errorString           = NULL;// must release
 	kernel_section_t      * infosect              = NULL;// do not free
-	OSSharedPtr<OSCollectionIterator>  personalitiesIterator;
+	OSCollectionIterator  * personalitiesIterator = NULL;// must release
 	unsigned int            count, i;
 
 	OSKextLog(/* kext */ NULL,
@@ -695,9 +920,9 @@
 	}
 
 	parsedXML = OSUnserializeXML((const char *) (uintptr_t)infosect->addr,
-	    errorString);
+	    &errorString);
 	if (parsedXML) {
-		builtinExtensions = OSDynamicCast(OSArray, parsedXML.get());
+		builtinExtensions = OSDynamicCast(OSArray, parsedXML);
 	}
 	if (!builtinExtensions) {
 		const char * errorCString = "(unknown error)";
@@ -724,6 +949,8 @@
 		OSDictionary            * personalities;// do not release
 		OSString                * personalityName;// do not release
 
+		OSSafeReleaseNULL(personalitiesIterator);
+
 		infoDict = OSDynamicCast(OSDictionary,
 		    builtinExtensions->getObject(i));
 		if (!infoDict) {
@@ -771,9 +998,13 @@
 		}
 	}
 
-	gIOCatalogue->addDrivers(allPersonalities.get(), false);
+	gIOCatalogue->addDrivers(allPersonalities, false);
 
 finish:
+	OSSafeReleaseNULL(parsedXML);
+	OSSafeReleaseNULL(allPersonalities);
+	OSSafeReleaseNULL(errorString);
+	OSSafeReleaseNULL(personalitiesIterator);
 	return;
 }