Implement support for linking on injected kext and fix minor issues

This commit is contained in:
vit9696 2019-03-21 00:36:27 +03:00
parent 6ed3156eea
commit 9be9d50677
10 changed files with 139 additions and 103 deletions

View File

@ -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.

View File

@ -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,

View File

@ -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]

View File

@ -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;
}

View File

@ -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"

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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) {

View File

@ -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,

View File

@ -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