mirror of
https://github.com/acidanthera/OpenCorePkg.git
synced 2025-12-08 19:25:01 +00:00
Implement support for linking on injected kext and fix minor issues
This commit is contained in:
parent
6ed3156eea
commit
9be9d50677
@ -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.
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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]
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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"
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
/** @file
|
||||
Library handling KEXT prelinking.
|
||||
Currently limited to Intel 64 architectures.
|
||||
|
||||
Copyright (c) 2018, Download-Fritz. All rights reserved.<BR>
|
||||
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 <Uefi.h>
|
||||
|
||||
#include <IndustryStandard/AppleMachoImage.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/OcGuardLib.h>
|
||||
#include <Library/OcMachoLib.h>
|
||||
#include <Library/OcAppleKernelLib.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
@ -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) {
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -20,10 +20,10 @@
|
||||
#include <sys/time.h>
|
||||
|
||||
/*
|
||||
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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user