From d8ace476067ebb4b5abe17e4cdcd094fa3641689 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Sun, 5 Jul 2020 23:18:10 +0300 Subject: [PATCH] OcAppleKernelLib: Fix patching KC vtables with imports from kexts --- .../Apple/IndustryStandard/AppleMachoImage.h | 2 +- Library/OcAppleKernelLib/KernelCollection.c | 6 ++-- Library/OcAppleKernelLib/Link.c | 3 +- Library/OcAppleKernelLib/PrelinkedInternal.h | 4 +++ Library/OcAppleKernelLib/Vtables.c | 36 ++++++++++++++++--- Utilities/TestKextInject/KextInject.c | 4 +++ 6 files changed, 46 insertions(+), 9 deletions(-) diff --git a/Include/Apple/IndustryStandard/AppleMachoImage.h b/Include/Apple/IndustryStandard/AppleMachoImage.h index 7505bf0a..07200d73 100644 --- a/Include/Apple/IndustryStandard/AppleMachoImage.h +++ b/Include/Apple/IndustryStandard/AppleMachoImage.h @@ -1805,7 +1805,7 @@ typedef struct { Key : 2, Next : 12, ///< 1 or 4-byte stide IsAuth : 1; ///< 0 -> not authenticated. 1 -> authenticated -} MACH_DYKD_CHAINED_PTR_64_KERNEL_CACHE_REBASE; +} MACH_DYLD_CHAINED_PTR_64_KERNEL_CACHE_REBASE; // header of the LC_DYLD_CHAINED_FIXUPS payload typedef struct { diff --git a/Library/OcAppleKernelLib/KernelCollection.c b/Library/OcAppleKernelLib/KernelCollection.c index f5f0ce06..101acd0c 100644 --- a/Library/OcAppleKernelLib/KernelCollection.c +++ b/Library/OcAppleKernelLib/KernelCollection.c @@ -444,11 +444,11 @@ InternalKcConvertRelocToFixup ( UINT16 NewFixupPage; UINT16 NewFixupPageOffset; - MACH_DYKD_CHAINED_PTR_64_KERNEL_CACHE_REBASE NewFixup; + MACH_DYLD_CHAINED_PTR_64_KERNEL_CACHE_REBASE NewFixup; UINT16 IterFixupPageOffset; VOID *IterFixupData; - MACH_DYKD_CHAINED_PTR_64_KERNEL_CACHE_REBASE IterFixup; + MACH_DYLD_CHAINED_PTR_64_KERNEL_CACHE_REBASE IterFixup; UINT16 NextIterFixupPageOffset; UINT16 FixupDelta; @@ -488,7 +488,7 @@ InternalKcConvertRelocToFixup ( // This 1MB here is a bit of a hack. I think it is just the same thing // as KERNEL_BASE_PADDR in OcAfterBootCompatLib. // - NewFixup.Target = ReadUnaligned64 (RelocDest) - BASE_1MB; + NewFixup.Target = ReadUnaligned64 (RelocDest) - KERNEL_FIXUP_OFFSET; NewFixupPage = (UINT16) (RelocOffsetInSeg / MACHO_PAGE_SIZE); NewFixupPageOffset = (UINT16) (RelocOffsetInSeg % MACHO_PAGE_SIZE); diff --git a/Library/OcAppleKernelLib/Link.c b/Library/OcAppleKernelLib/Link.c index 7db73c96..b4e500ce 100644 --- a/Library/OcAppleKernelLib/Link.c +++ b/Library/OcAppleKernelLib/Link.c @@ -1405,10 +1405,11 @@ InternalPrelinkKext64 ( // // Undefined symbols are solved via their name. // + SymbolName = MachoGetSymbolName64 (MachoContext, Symbol); Result = InternalSolveSymbol64 ( Context, Kext, - MachoGetSymbolName64 (MachoContext, Symbol), + SymbolName, Symbol, &WeakTestValue, UndefinedSymtab, diff --git a/Library/OcAppleKernelLib/PrelinkedInternal.h b/Library/OcAppleKernelLib/PrelinkedInternal.h index b2888eab..2222873a 100644 --- a/Library/OcAppleKernelLib/PrelinkedInternal.h +++ b/Library/OcAppleKernelLib/PrelinkedInternal.h @@ -257,6 +257,10 @@ InternalConnectExternalSymtab ( #define VTABLE_HEADER_LEN_64 2U #define VTABLE_HEADER_SIZE_64 (VTABLE_HEADER_LEN_64 * VTABLE_ENTRY_SIZE_64) +#define KERNEL_ADDRESS_MASK 0xFFFFFFFF00000000ULL +#define KERNEL_ADDRESS_BASE 0xFFFFFF8000000000ULL +#define KERNEL_FIXUP_OFFSET BASE_1MB + typedef union { struct { UINT32 Major : 14; diff --git a/Library/OcAppleKernelLib/Vtables.c b/Library/OcAppleKernelLib/Vtables.c index c6d8db71..00e88db6 100644 --- a/Library/OcAppleKernelLib/Vtables.c +++ b/Library/OcAppleKernelLib/Vtables.c @@ -96,10 +96,11 @@ InternalConstructVtablePrelinked64 ( OUT PRELINKED_VTABLE *Vtable ) { - CONST UINT64 *VtableData; - UINT64 Value; - UINT32 Index; - CONST PRELINKED_KEXT_SYMBOL *Symbol; + CONST UINT64 *VtableData; + UINT64 Value; + UINT32 Index; + CONST PRELINKED_KEXT_SYMBOL *Symbol; + MACH_DYLD_CHAINED_PTR_64_KERNEL_CACHE_REBASE *Rebase; ASSERT (Kext != NULL); ASSERT (VtableLookup != NULL); @@ -123,6 +124,32 @@ InternalConstructVtablePrelinked64 ( (Value = VtableData[Index + VTABLE_HEADER_LEN_64]) != 0; ++Index ) { + + // + // For all non-kernel (which uses own relocation) virtual tables + // all virtual tables will contain fixups exclusively. + // For now we will just detect them by the kernel address + // as it is faster than compare Kext->Identifier and Context->IsKernelCollection. + // + if ((Value & KERNEL_ADDRESS_MASK) != KERNEL_ADDRESS_BASE) { + // + // FIXME: This needs a bit more love with aliasing and alignment. + // Some day, when Intel rewrites EDK II. + // + Rebase = (MACH_DYLD_CHAINED_PTR_64_KERNEL_CACHE_REBASE *)(UINTN) &Value; + DEBUG_CODE_BEGIN (); + if (Rebase->CacheLevel != 0 + || Rebase->Diversity != 0 + || Rebase->AddrDiv != 0 + || Rebase->Key != 0 + || Rebase->IsAuth != 0) { + DEBUG ((DEBUG_INFO, "OCAK: Invalid fixup %Lx in %a for %a\n", Value, Vtable->Name, Kext->Identifier)); + } + DEBUG_CODE_END (); + + Value = Rebase->Target + KERNEL_FIXUP_OFFSET + KERNEL_ADDRESS_BASE; + } + // // If we can't find the symbol, it means that the virtual function was // defined inline. There's not much I can do about this; it just means @@ -205,6 +232,7 @@ InternalPrepareCreateVtablesPrelinked64 ( // __ZTV20IOACPIPlatformDevice // if (Symbol->Value == 0) { + DEBUG ((DEBUG_VERBOSE, "OCAK: Skipping %a with NULL value\n", Symbol->Name)); continue; } diff --git a/Utilities/TestKextInject/KextInject.c b/Utilities/TestKextInject/KextInject.c index 73aa98be..85a2e669 100644 --- a/Utilities/TestKextInject/KextInject.c +++ b/Utilities/TestKextInject/KextInject.c @@ -446,6 +446,10 @@ GetFileSize ( } int wrap_main(int argc, char** argv) { + PcdGet32 (PcdFixedDebugPrintErrorLevel) |= DEBUG_INFO; + PcdGet32 (PcdDebugPrintErrorLevel) |= DEBUG_INFO; + + UINT32 AllocSize; PRELINKED_CONTEXT Context; const char *name = argc > 1 ? argv[1] : "/System/Library/PrelinkedKernels/prelinkedkernel"; -- GitLab