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