diff --git a/Include/Library/OcAppleKernelLib.h b/Include/Library/OcAppleKernelLib.h
index 5a14c01d..ae4ce4f2 100644
--- a/Include/Library/OcAppleKernelLib.h
+++ b/Include/Library/OcAppleKernelLib.h
@@ -311,25 +311,6 @@ PrelinkedInjectKext (
IN UINT32 ExecutableSize OPTIONAL
);
-/**
- Link executable within current prelink context.
-
- @param[in,out] Context Prelinked context.
- @param[in,out] Executable Kext executable copied to prelinked.
- @param[in] ExecutableSize Kext executable size.
- @param[in] PlistRoot Current kext info.plist.
- @param[out] LoadAddress Resulting kext load address.
-
- @return EFI_SUCCESS on success.
-**/
-EFI_STATUS
-PrelinkedLinkExecutable (
- IN OUT PRELINKED_CONTEXT *Context,
- IN OUT OC_MACHO_CONTEXT *Executable,
- IN XML_NODE *PlistRoot,
- IN UINT64 LoadAddress
- );
-
/**
Initialize patcher from prelinked context for kext patching.
diff --git a/Library/OcAppleKernelLib/Link.c b/Library/OcAppleKernelLib/Link.c
index 2054c06b..1e671728 100644
--- a/Library/OcAppleKernelLib/Link.c
+++ b/Library/OcAppleKernelLib/Link.c
@@ -198,8 +198,8 @@ InternalSolveSymbolNonWeak64 (
INTN Result;
CONST PRELINKED_KEXT_SYMBOL *ResolveSymbol;
- if (Symbol->Type != MACH_N_TYPE_UNDF) {
- if (Symbol->Type != MACH_N_TYPE_INDR) {
+ if ((Symbol->Type & MACH_N_TYPE_TYPE) != MACH_N_TYPE_UNDF) {
+ if ((Symbol->Type & MACH_N_TYPE_TYPE) != MACH_N_TYPE_INDR) {
//
// KXLD_WEAK_TEST_SYMBOL might have been resolved by the resolving code
// at the end of InternalSolveSymbol64.
@@ -1004,7 +1004,7 @@ InternalStripLoadCommands64 (
SizeOfLeftCommands -= LoadCommand->CommandSize;
- for (Index2 = 0; Index < ARRAY_SIZE (LoadCommandsToStrip); ++Index2) {
+ for (Index2 = 0; Index2 < ARRAY_SIZE (LoadCommandsToStrip); ++Index2) {
if (LoadCommand->CommandType == LoadCommandsToStrip[Index2]) {
if (Index != (MachHeader->NumCommands - 1)) {
//
@@ -1277,7 +1277,7 @@ InternalPrelinkKext64 (
Result = InternalRelocateAndCopyRelocations64 (
MachoContext,
LoadAddress,
- DependencyData->Vtables,
+ /* DependencyData->Vtables */ NULL,
RelocationBase,
Relocations,
&NumRelocations,
@@ -1292,7 +1292,7 @@ InternalPrelinkKext64 (
Result = InternalRelocateAndCopyRelocations64 (
MachoContext,
LoadAddress,
- DependencyData->Vtables,
+ /* DependencyData->Vtables */ NULL,
RelocationBase,
Relocations,
&NumRelocations2,
diff --git a/Library/OcAppleKernelLib/OcAppleKernelLib.inf b/Library/OcAppleKernelLib/OcAppleKernelLib.inf
index 06a7a8b9..4bf92bed 100644
--- a/Library/OcAppleKernelLib/OcAppleKernelLib.inf
+++ b/Library/OcAppleKernelLib/OcAppleKernelLib.inf
@@ -29,7 +29,6 @@
#
[Sources]
- Dependencies.c
KernelReader.c
KextPatcher.c
Link.c
@@ -37,7 +36,6 @@
PrelinkedContext.c
PrelinkedInternal.h
PrelinkedKext.c
- Prelinker.c
Vtables.c
[Packages]
diff --git a/Library/OcAppleKernelLib/PrelinkedContext.c b/Library/OcAppleKernelLib/PrelinkedContext.c
index 44bd9914..b70362d9 100644
--- a/Library/OcAppleKernelLib/PrelinkedContext.c
+++ b/Library/OcAppleKernelLib/PrelinkedContext.c
@@ -466,11 +466,14 @@ PrelinkedInjectKext (
UINT32 AlignedExecutableSize;
BOOLEAN Failed;
UINT64 KmodAddress;
+ PRELINKED_KEXT *PrelinkedKext;
CHAR8 ExecutableSourceAddrStr[24];
CHAR8 ExecutableSizeStr[24];
CHAR8 ExecutableLoadAddrStr[24];
CHAR8 KmodInfoStr[24];
+ PrelinkedKext = NULL;
+
//
// Copy executable to prelinkedkernel.
//
@@ -550,17 +553,18 @@ PrelinkedInjectKext (
}
if (Executable != NULL) {
- Status = PrelinkedLinkExecutable (
+ PrelinkedKext = InternalLinkPrelinkedKext (
Context,
&ExecutableContext,
InfoPlistRoot,
- Context->PrelinkedLastAddress
+ Context->PrelinkedLastAddress,
+ KmodAddress
);
- if (EFI_ERROR (Status)) {
+ if (PrelinkedKext == NULL) {
XmlDocumentFree (InfoPlistDocument);
FreePool (TmpInfoPlist);
- return Status;
+ return EFI_INVALID_PARAMETER;
}
//
@@ -585,18 +589,34 @@ PrelinkedInjectKext (
FreePool (TmpInfoPlist);
if (NewInfoPlist == NULL) {
+ if (PrelinkedKext != NULL) {
+ InternalFreePrelinkedKext (PrelinkedKext);
+ }
return EFI_OUT_OF_RESOURCES;
}
Status = PrelinkedDependencyInsert (Context, NewInfoPlist);
if (EFI_ERROR (Status)) {
FreePool (NewInfoPlist);
+ if (PrelinkedKext != NULL) {
+ InternalFreePrelinkedKext (PrelinkedKext);
+ }
return Status;
}
if (XmlNodeAppend (Context->KextList, "dict", NULL, NewInfoPlist) == NULL) {
+ if (PrelinkedKext != NULL) {
+ InternalFreePrelinkedKext (PrelinkedKext);
+ }
return EFI_OUT_OF_RESOURCES;
}
+ //
+ // Let other kexts depend on this one.
+ //
+ if (PrelinkedKext != NULL) {
+ InsertTailList (&Context->PrelinkedKexts, &PrelinkedKext->Link);
+ }
+
return EFI_SUCCESS;
}
diff --git a/Library/OcAppleKernelLib/PrelinkedInternal.h b/Library/OcAppleKernelLib/PrelinkedInternal.h
index 6a3ab2b6..f599b210 100644
--- a/Library/OcAppleKernelLib/PrelinkedInternal.h
+++ b/Library/OcAppleKernelLib/PrelinkedInternal.h
@@ -51,7 +51,8 @@ struct PRELINKED_KEXT_ {
//
PATCHER_CONTEXT Context;
//
- // Dependencies dictionary (OSBundleLibraries), may be NULL for KPI kexts.
+ // Dependencies dictionary (OSBundleLibraries).
+ // May be NULL for KPI kexts or after Dependencies are set.
//
XML_NODE *BundleLibraries;
//
@@ -144,6 +145,26 @@ InternalScanPrelinkedKext (
IN OUT PRELINKED_CONTEXT *Context
);
+/**
+ Link executable within current prelink context.
+
+ @param[in,out] Context Prelinked context.
+ @param[in,out] Executable Kext executable copied to prelinked.
+ @param[in] ExecutableSize Kext executable size.
+ @param[in] PlistRoot Current kext info.plist.
+ @param[in] LoadAddress Kext load address.
+ @param[in] KmodAddress Kext kmod address.
+
+ @return prelinked kext to be inserted into PRELINKED_CONTEXT.
+**/
+PRELINKED_KEXT *
+InternalLinkPrelinkedKext (
+ IN OUT PRELINKED_CONTEXT *Context,
+ IN OUT OC_MACHO_CONTEXT *Executable,
+ IN XML_NODE *PlistRoot,
+ IN UINT64 LoadAddress,
+ IN UINT64 KmodAddress
+ );
#define KXLD_WEAK_TEST_SYMBOL "_gOSKextUnresolved"
diff --git a/Library/OcAppleKernelLib/PrelinkedKext.c b/Library/OcAppleKernelLib/PrelinkedKext.c
index 484c5a61..ba79e7a0 100644
--- a/Library/OcAppleKernelLib/PrelinkedKext.c
+++ b/Library/OcAppleKernelLib/PrelinkedKext.c
@@ -216,7 +216,7 @@ InternalScanBuildLinkedSymbolTable (
BOOLEAN Result;
if (Kext->LinkedSymbolTable != NULL) {
- return EFI_ALREADY_STARTED;
+ return EFI_SUCCESS;
}
SymbolTable = AllocatePool (Kext->NumberOfSymbols * sizeof (*SymbolTable));
@@ -347,10 +347,6 @@ InternalScanPrelinkedKext (
CONST CHAR8 *DependencyId;
PRELINKED_KEXT *DependencyKext;
- if (Kext->Dependencies[0] != NULL) {
- return EFI_ALREADY_STARTED;
- }
-
if (Kext->BundleLibraries == NULL) {
return EFI_SUCCESS;
}
@@ -378,12 +374,12 @@ InternalScanPrelinkedKext (
}
Status = InternalScanPrelinkedKext (DependencyKext, Context);
- if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+ if (EFI_ERROR (Status)) {
return Status;
}
Status = InternalScanBuildLinkedSymbolTable (DependencyKext);
- if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+ if (EFI_ERROR (Status)) {
return Status;
}
@@ -391,5 +387,82 @@ InternalScanPrelinkedKext (
++DependencyIndex;
}
+ //
+ // We do not need this anymore.
+ // Additionally it may point to invalid memory on prelinked kexts.
+ //
+ Kext->BundleLibraries = NULL;
+
return EFI_SUCCESS;
}
+
+PRELINKED_KEXT *
+InternalLinkPrelinkedKext (
+ IN OUT PRELINKED_CONTEXT *Context,
+ IN OUT OC_MACHO_CONTEXT *Executable,
+ IN XML_NODE *PlistRoot,
+ IN UINT64 LoadAddress,
+ IN UINT64 KmodAddress
+ )
+{
+ EFI_STATUS Status;
+ PRELINKED_KEXT *Kext;
+
+ Kext = InternalNewPrelinkedKext (Executable, PlistRoot);
+ if (Kext == NULL) {
+ return NULL;
+ }
+
+ Status = InternalScanPrelinkedKext (Kext, Context);
+ if (EFI_ERROR (Status)) {
+ InternalFreePrelinkedKext (Kext);
+ return NULL;
+ }
+
+ //
+ // Detach Identifier from temporary memory location.
+ //
+ Kext->Identifier = AllocateCopyPool (AsciiStrSize (Kext->Identifier), Kext->Identifier);
+ if (Kext->Identifier == NULL) {
+ InternalFreePrelinkedKext (Kext);
+ return NULL;
+ }
+
+ Status = PrelinkedDependencyInsert (Context, (CHAR8 *) Kext->Identifier);
+ if (EFI_ERROR (Status)) {
+ FreePool ((CHAR8 *) Kext->Identifier);
+ InternalFreePrelinkedKext (Kext);
+ return NULL;
+ }
+ //
+ // Also detach bundle compatible version if any.
+ //
+ if (Kext->CompatibleVersion != NULL) {
+ Kext->CompatibleVersion = AllocateCopyPool (AsciiStrSize (Kext->CompatibleVersion), Kext->CompatibleVersion);
+ if (Kext->CompatibleVersion == NULL) {
+ InternalFreePrelinkedKext (Kext);
+ return NULL;
+ }
+
+ Status = PrelinkedDependencyInsert (Context, (CHAR8 *) Kext->CompatibleVersion);
+ if (EFI_ERROR (Status)) {
+ FreePool ((CHAR8 *) Kext->CompatibleVersion);
+ InternalFreePrelinkedKext (Kext);
+ return NULL;
+ }
+ }
+ //
+ // Set virtual addresses.
+ //
+ Kext->Context.VirtualBase = LoadAddress;
+ Kext->Context.VirtualKmod = KmodAddress;
+
+ Status = InternalPrelinkKext64 (Context, Kext, LoadAddress);
+
+ if (EFI_ERROR (Status)) {
+ InternalFreePrelinkedKext (Kext);
+ return NULL;
+ }
+
+ return Kext;
+}
diff --git a/Library/OcAppleKernelLib/Prelinker.c b/Library/OcAppleKernelLib/Prelinker.c
deleted file mode 100644
index a46b2f81..00000000
--- a/Library/OcAppleKernelLib/Prelinker.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/** @file
- Library handling KEXT prelinking.
- Currently limited to Intel 64 architectures.
-
-Copyright (c) 2018, Download-Fritz. All rights reserved.
-This program and the accompanying materials are licensed and made available
-under the terms and conditions of the BSD License which accompanies this
-distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php.
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include
-
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "PrelinkedInternal.h"
-
-EFI_STATUS
-PrelinkedLinkExecutable (
- IN OUT PRELINKED_CONTEXT *Context,
- IN OUT OC_MACHO_CONTEXT *Executable,
- IN XML_NODE *PlistRoot,
- IN UINT64 LoadAddress
- )
-{
- EFI_STATUS Status;
- PRELINKED_KEXT *Kext;
-
- Kext = InternalNewPrelinkedKext (Executable, PlistRoot);
- if (Kext == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- Status = InternalScanPrelinkedKext (Kext, Context);
- if (EFI_ERROR (Status)) {
- InternalFreePrelinkedKext (Kext);
- return Status;
- }
-
- Status = InternalPrelinkKext64 (Context, Kext, LoadAddress);
-
- InternalFreePrelinkedKext (Kext);
-
- return Status;
-}
diff --git a/Library/OcAppleKernelLib/Vtables.c b/Library/OcAppleKernelLib/Vtables.c
index 9e29084a..d36720c3 100644
--- a/Library/OcAppleKernelLib/Vtables.c
+++ b/Library/OcAppleKernelLib/Vtables.c
@@ -612,7 +612,7 @@ InternalCreateVtablesNonPrelinked64 (
// Get the super vtable if it's been patched
//
SuperVtable = InternalGetOcVtableByName (
- DependencyData->Vtables,
+ /* DependencyData->Vtables */ NULL,
SuperVtableName
);
if (SuperVtable == NULL) {
@@ -688,7 +688,7 @@ InternalCreateVtablesNonPrelinked64 (
}
MetaVtable = InternalGetOcVtableByName (
- DependencyData->Vtables,
+ /* DependencyData->Vtables */ NULL,
VtableName
);
if (MetaVtable != NULL) {
@@ -700,7 +700,7 @@ InternalCreateVtablesNonPrelinked64 (
// OSMetaClass, so we just hardcode that vtable name here.
//
SuperVtable = InternalGetOcVtableByName (
- DependencyData->Vtables,
+ /* DependencyData->Vtables */ NULL,
OS_METACLASS_VTABLE_NAME
);
if (SuperVtable == NULL) {
diff --git a/Library/OcMachoPrelinkLib/Prelink.c b/Library/OcMachoPrelinkLib/Prelink.c
index 10d0765d..7f55260d 100644
--- a/Library/OcMachoPrelinkLib/Prelink.c
+++ b/Library/OcMachoPrelinkLib/Prelink.c
@@ -128,8 +128,8 @@ InternalSolveSymbolNonWeak64 (
INTN Result;
CONST OC_SYMBOL_64 *ResolveSymbol;
- if (Symbol->Type != MACH_N_TYPE_UNDF) {
- if (Symbol->Type != MACH_N_TYPE_INDR) {
+ if ((Symbol->Type & MACH_N_TYPE_TYPE) != MACH_N_TYPE_UNDF) {
+ if ((Symbol->Type & MACH_N_TYPE_TYPE) != MACH_N_TYPE_INDR) {
//
// KXLD_WEAK_TEST_SYMBOL might have been resolved by the resolving code
// at the end of InternalSolveSymbol64.
@@ -239,7 +239,7 @@ InternalSolveSymbol64 (
KXLD_WEAK_TEST_SYMBOL
);
if (Result == 0) {
- if (WeakTestSymbol->Type == MACH_N_TYPE_UNDF) {
+ if ((WeakTestSymbol->Type & MACH_N_TYPE_TYPE) == MACH_N_TYPE_UNDF) {
Success = InternalSolveSymbolNonWeak64 (
MachoContext,
DefinedSymbols,
diff --git a/TestsUser/Prelinked/Prelinked.c b/TestsUser/Prelinked/Prelinked.c
index 4918962d..952c5654 100644
--- a/TestsUser/Prelinked/Prelinked.c
+++ b/TestsUser/Prelinked/Prelinked.c
@@ -20,10 +20,10 @@
#include
/*
- clang -g -fsanitize=undefined,address -Wno-incompatible-pointer-types-discards-qualifiers -I../Include -I../../Include -I../../../MdePkg/Include/ -I../../../EfiPkg/Include/ -include ../Include/Base.h Prelinked.c ../../Library/OcXmlLib/OcXmlLib.c ../../Library/OcTemplateLib/OcTemplateLib.c ../../Library/OcSerializeLib/OcSerializeLib.c ../../Library/OcMiscLib/Base64Decode.c ../../Library/OcStringLib/OcAsciiLib.c ../../Library/OcMachoLib/CxxSymbols.c ../../Library/OcMachoLib/Header.c ../../Library/OcMachoLib/Relocations.c ../../Library/OcMachoLib/Symbols.c ../../Library/OcAppleKernelLib/PrelinkedContext.c ../../Library/OcAppleKernelLib/PrelinkedKext.c ../../Library/OcAppleKernelLib/KextPatcher.c ../../Library/OcMiscLib/DataPatcher.c ../../Library/OcAppleKernelLib/Prelinker.c ../../Library/OcAppleKernelLib/Link.c ../../Library/OcAppleKernelLib/Dependencies.c ../../Library/OcAppleKernelLib/Vtables.c -o Prelinked
+ clang -g -fsanitize=undefined,address -Wno-incompatible-pointer-types-discards-qualifiers -I../Include -I../../Include -I../../../MdePkg/Include/ -I../../../EfiPkg/Include/ -include ../Include/Base.h Prelinked.c ../../Library/OcXmlLib/OcXmlLib.c ../../Library/OcTemplateLib/OcTemplateLib.c ../../Library/OcSerializeLib/OcSerializeLib.c ../../Library/OcMiscLib/Base64Decode.c ../../Library/OcStringLib/OcAsciiLib.c ../../Library/OcMachoLib/CxxSymbols.c ../../Library/OcMachoLib/Header.c ../../Library/OcMachoLib/Relocations.c ../../Library/OcMachoLib/Symbols.c ../../Library/OcAppleKernelLib/PrelinkedContext.c ../../Library/OcAppleKernelLib/PrelinkedKext.c ../../Library/OcAppleKernelLib/KextPatcher.c ../../Library/OcMiscLib/DataPatcher.c ../../Library/OcAppleKernelLib/Link.c ../../Library/OcAppleKernelLib/Vtables.c -o Prelinked
for fuzzing:
- clang-mp-7.0 -Dmain=__main -g -fsanitize=undefined,address,fuzzer -Wno-incompatible-pointer-types-discards-qualifiers -I../Include -I../../Include -I../../../MdePkg/Include/ -I../../../EfiPkg/Include/ -include ../Include/Base.h Prelinked.c ../../Library/OcXmlLib/OcXmlLib.c ../../Library/OcTemplateLib/OcTemplateLib.c ../../Library/OcSerializeLib/OcSerializeLib.c ../../Library/OcMiscLib/Base64Decode.c ../../Library/OcStringLib/OcAsciiLib.c ../../Library/OcMachoLib/CxxSymbols.c ../../Library/OcMachoLib/Header.c ../../Library/OcMachoLib/Relocations.c ../../Library/OcMachoLib/Symbols.c ../../Library/OcAppleKernelLib/PrelinkedContext.c ../../Library/OcAppleKernelLib/PrelinkedKext.c ../../Library/OcAppleKernelLib/KextPatcher.c ../../Library/OcMiscLib/DataPatcher.c ../../Library/OcAppleKernelLib/Prelinker.c ../../Library/OcAppleKernelLib/Link.c ../../Library/OcAppleKernelLib/Dependencies.c ../../Library/OcAppleKernelLib/Vtables.c -o Prelinked
+ clang-mp-7.0 -Dmain=__main -g -fsanitize=undefined,address,fuzzer -Wno-incompatible-pointer-types-discards-qualifiers -I../Include -I../../Include -I../../../MdePkg/Include/ -I../../../EfiPkg/Include/ -include ../Include/Base.h Prelinked.c ../../Library/OcXmlLib/OcXmlLib.c ../../Library/OcTemplateLib/OcTemplateLib.c ../../Library/OcSerializeLib/OcSerializeLib.c ../../Library/OcMiscLib/Base64Decode.c ../../Library/OcStringLib/OcAsciiLib.c ../../Library/OcMachoLib/CxxSymbols.c ../../Library/OcMachoLib/Header.c ../../Library/OcMachoLib/Relocations.c ../../Library/OcMachoLib/Symbols.c ../../Library/OcAppleKernelLib/PrelinkedContext.c ../../Library/OcAppleKernelLib/PrelinkedKext.c ../../Library/OcAppleKernelLib/KextPatcher.c ../../Library/OcMiscLib/DataPatcher.c ../../Library/OcAppleKernelLib/Link.c ../../Library/OcAppleKernelLib/Vtables.c -o Prelinked
rm -rf DICT fuzz*.log ; mkdir DICT ; cp Prelinked.plist DICT ; ./Prelinked -jobs=4 DICT
rm -rf Prelinked.dSYM DICT fuzz*.log Prelinked