- prelinkTextSegment = getsegbyname(kPrelinkTextSegment);
- if (!prelinkTextSegment) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel |
- kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
- "Can't find prelinked kexts' text segment.");
- goto finish;
- }
-
- prelinkData = (void *) prelinkTextSegment->vmaddr;
- prelinkLength = prelinkTextSegment->vmsize;
-
-#if !__LP64__
- /* To enable paging and write/execute protections on the kext
- * executables, we need to copy them out of the booter-created
- * memory, reallocate that space with VM, then prelinkCopy them back in.
- * This isn't necessary on LP64 because kexts have their own VM
- * region on that architecture model.
- */
-
- mem_result = kmem_alloc(kernel_map, (vm_offset_t *)&prelinkCopy,
- prelinkLength);
- if (mem_result != KERN_SUCCESS) {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel |
- kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
- "Can't copy prelinked kexts' text for VM reassign.");
- goto finish;
- }
-
- /* Copy it out.
- */
- memcpy(prelinkCopy, prelinkData, prelinkLength);
-
- /* Dump the booter memory.
- */
- ml_static_mfree((vm_offset_t)prelinkData, prelinkLength);
-
- /* Set up the VM region.
- */
- prelinkDataMapOffset = (vm_map_offset_t)(uintptr_t)prelinkData;
- mem_result = vm_map_enter_mem_object(
- kernel_map,
- &prelinkDataMapOffset,
- prelinkLength, /* mask */ 0,
- VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE,
- (ipc_port_t)NULL,
- (vm_object_offset_t) 0,
- /* copy */ FALSE,
- /* cur_protection */ VM_PROT_ALL,
- /* max_protection */ VM_PROT_ALL,
- /* inheritance */ VM_INHERIT_DEFAULT);
- if ((mem_result != KERN_SUCCESS) ||
- (prelinkTextSegment->vmaddr != prelinkDataMapOffset))
- {
- OSKextLog(/* kext */ NULL,
- kOSKextLogErrorLevel |
- kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
- "Can't create kexts' text VM entry at 0x%llx, length 0x%x (error 0x%x).",
- (unsigned long long) prelinkDataMapOffset, prelinkLength, mem_result);
- goto finish;
- }
- prelinkData = (void *)(uintptr_t)prelinkDataMapOffset;
-
- /* And copy it back.
- */
- memcpy(prelinkData, prelinkCopy, prelinkLength);
-
- kmem_free(kernel_map, (vm_offset_t)prelinkCopy, prelinkLength);
-#endif /* !__LP64__ */
-
- /* Unserialize the info dictionary from the prelink info section.
- */
- parsedXML = OSUnserializeXML((const char *)prelinkInfoSect->addr,
- &errorString);
- if (parsedXML) {
- prelinkInfoDict = OSDynamicCast(OSDictionary, parsedXML);
- }
- if (!prelinkInfoDict) {
- 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 prelink plist: %s.", errorCString);
- goto finish;
- }
-
- infoDictArray = OSDynamicCast(OSArray,
- prelinkInfoDict->getObject(kPrelinkInfoDictionaryKey));
- if (!infoDictArray) {
- OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
- "The prelinked kernel has no kext info dictionaries");
- goto finish;
- }
-
- /* 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;
- }
-
- /* 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);
- OSSafeReleaseNULL(newKext);
- }
-
- /* Get all of the personalities for kexts that were not prelinked and
- * add them to the catalogue.
- */
- personalitiesArray = OSDynamicCast(OSArray,
- prelinkInfoDict->getObject(kPrelinkPersonalitiesKey));
- if (!personalitiesArray) {
- OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
- "The prelinked kernel has no personalities array");
- goto finish;
- }
-
- if (personalitiesArray->getCount()) {
- OSKext::setPrelinkedPersonalities(personalitiesArray);
- }
-
- /* 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);
-
- prelinkCountObj = OSNumber::withNumber(
- (unsigned long long)infoDictArray->getCount(),
- 8 * sizeof(uint32_t));
- assert(prelinkCountObj);
- if (prelinkCountObj) {
- registryRoot->setProperty(kOSPrelinkKextCountKey, prelinkCountObj);
- }
-
- OSSafeReleaseNULL(prelinkCountObj);
- prelinkCountObj = OSNumber::withNumber(
- (unsigned long long)personalitiesArray->getCount(),
- 8 * sizeof(uint32_t));
- assert(prelinkCountObj);
- if (prelinkCountObj) {
- registryRoot->setProperty(kOSPrelinkPersonalityCountKey, prelinkCountObj);
- }
-
- OSKextLog(/* kext */ NULL,
- kOSKextLogProgressLevel |
- kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag |
- kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
- "%u prelinked kexts, and %u additional personalities.",
- infoDictArray->getCount(), personalitiesArray->getCount());
-
-#if __LP64__
- /* On LP64 systems, kexts are copied to their own special VM region
- * during OSKext init time, so we can free the whole segment now.
- */
- ml_static_mfree((vm_offset_t) prelinkData, prelinkLength);
-#endif /* __LP64__ */
-
- /* Free the link state segment, kexts have copied out what they need.
- */
- prelinkLinkStateSegment = getsegbyname(kPrelinkLinkStateSegment);
- if (prelinkLinkStateSegment) {
- ml_static_mfree((vm_offset_t)prelinkLinkStateSegment->vmaddr,
- (vm_size_t)prelinkLinkStateSegment->vmsize);
- }
-
- /* Free the prelink info segment, we're done with it.
- */
- prelinkInfoSegment = getsegbyname(kPrelinkInfoSegment);
- if (prelinkInfoSegment) {
- ml_static_mfree((vm_offset_t)prelinkInfoSegment->vmaddr,
- (vm_size_t)prelinkInfoSegment->vmsize);
- }
+ 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.
+ */
+ 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
+ /* 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.
+ */
+ ml_static_mfree((vm_offset_t) prelinkData, prelinkLength);
+#endif /* __x86_64__ */
+
+ /* Free the prelink info segment, we're done with it.
+ */
+ prelinkInfoSegment = getsegbyname(kPrelinkInfoSegment);
+ if (prelinkInfoSegment) {
+ ml_static_mfree((vm_offset_t)prelinkInfoSegment->vmaddr,
+ (vm_size_t)prelinkInfoSegment->vmsize);
+ }