未验证 提交 74062d4e 编写于 作者: J John Davis 提交者: GitHub

OcAppleKernelLib: Add 32-bit Mach-O and patching support (#118)

上级 18ce64b4
......@@ -2166,7 +2166,7 @@ blocking.
\texttt{AppleCpuPmCfgLock}\\
\textbf{Type}: \texttt{plist\ boolean}\\
\textbf{Failsafe}: \texttt{false}\\
\textbf{Requirement}: 10.6 (64-bit)\\
\textbf{Requirement}: 10.4\\
\textbf{Description}: Disables \texttt{PKG\_CST\_CONFIG\_CONTROL} (\texttt{0xE2})
MSR modification in AppleIntelCPUPowerManagement.kext, commonly causing early
kernel panic, when it is locked from writing.
......@@ -2247,7 +2247,7 @@ blocking.
\texttt{CustomSMBIOSGuid}\\
\textbf{Type}: \texttt{plist\ boolean}\\
\textbf{Failsafe}: \texttt{false}\\
\textbf{Requirement}: 10.6 (64-bit)\\
\textbf{Requirement}: 10.4\\
\textbf{Description}: Performs GUID patching for \texttt{UpdateSMBIOSMode}
\texttt{Custom} mode. Usually relevant for Dell laptops.
......@@ -2278,7 +2278,7 @@ blocking.
\texttt{DisableRtcChecksum}\\
\textbf{Type}: \texttt{plist\ boolean}\\
\textbf{Failsafe}: \texttt{false}\\
\textbf{Requirement}: 10.6 (64-bit)\\
\textbf{Requirement}: 10.4\\
\textbf{Description}: Disables primary checksum (\texttt{0x58}-\texttt{0x59})
writing in AppleRTC.
......@@ -2294,7 +2294,7 @@ blocking.
\texttt{DummyPowerManagement}\\
\textbf{Type}: \texttt{plist\ boolean}\\
\textbf{Failsafe}: \texttt{false}\\
\textbf{Requirement}: 10.6 (64-bit)\\
\textbf{Requirement}: 10.4\\
\textbf{Description}: Disables \texttt{AppleIntelCpuPowerManagement}.
\emph{Note}: This option is a preferred alternative to
......@@ -2305,7 +2305,7 @@ blocking.
\texttt{ExternalDiskIcons}\\
\textbf{Type}: \texttt{plist\ boolean}\\
\textbf{Failsafe}: \texttt{false}\\
\textbf{Requirement}: 10.6 (64-bit)\\
\textbf{Requirement}: 10.4\\
\textbf{Description}: Apply icon type patches to AppleAHCIPort.kext to force
internal disk icons for all AHCI disks.
......@@ -2354,7 +2354,7 @@ blocking.
\texttt{ThirdPartyDrives}\\
\textbf{Type}: \texttt{plist\ boolean}\\
\textbf{Failsafe}: \texttt{false}\\
\textbf{Requirement}: 10.6 (64-bit, not required for older)\\
\textbf{Requirement}: 10.6 (not required for older)\\
\textbf{Description}: Apply vendor patches to IOAHCIBlockStorage.kext to enable
native features for third-party drives, such as TRIM on SSDs or hibernation
support on 10.15 and newer.
......@@ -2515,13 +2515,13 @@ refer to \hyperref[legacyapple]{Legacy Apple OS}.
\hline
\textbf{macOS} & \textbf{i386 NC} & \textbf{i386 MK} & \textbf{i386 PK} & \textbf{x86\_64 NC} & \textbf{x86\_64 MK} & \textbf{x86\_64 PK} & \textbf{x86\_64 KC} \\
\hline
10.4 & NO & NO (V1) & NO & --- & --- & --- & --- \\
10.4 & YES & YES (V1) & NO & --- & --- & --- & --- \\
\hline
10.5 & NO & NO (V1) & NO & --- & --- & --- & --- \\
10.5 & YES & YES (V1) & NO & --- & --- & --- & --- \\
\hline
10.6 & NO & NO (V2) & NO & YES & YES (V2) & YES & --- \\
10.6 & YES & YES (V2) & NO & YES & YES (V2) & YES & --- \\
\hline
10.7 & NO & --- & NO & YES & --- & YES & --- \\
10.7 & YES & --- & NO & YES & --- & YES & --- \\
\hline
10.8-10.9 & --- & --- & --- & YES & --- & YES & --- \\
\hline
......
......@@ -74,6 +74,7 @@
// Kernel cache types.
//
typedef enum KERNEL_CACHE_TYPE_ {
CacheTypeNone,
CacheTypeCacheless,
CacheTypeMkext,
CacheTypePrelinked
......@@ -85,7 +86,7 @@ typedef enum KERNEL_CACHE_TYPE_ {
#define PRINT_KERNEL_CACHE_TYPE(a) ( \
(a) == CacheTypeCacheless ? "Cacheless" : \
((a) == CacheTypeMkext ? "Mkext" : \
(((a) == CacheTypePrelinked ? "Prelinked" : "Unknown"))))
(((a) == CacheTypePrelinked ? "Prelinked" : "Kernel"))))
//
// As PageCount is UINT16, we can only index 2^16 * 4096 Bytes with one chain.
......@@ -311,10 +312,14 @@ typedef struct {
//
OC_MACHO_CONTEXT MachContext;
//
// Virtual base to subtract to obtain file offset.
// Virtual base of text segment.
//
UINT64 VirtualBase;
//
// File offset.
//
UINT64 FileOffset;
//
// Virtual kmod_info_t address.
//
UINT64 VirtualKmod;
......@@ -327,9 +332,13 @@ typedef struct {
//
UINT32 KxldStateSize;
//
// Binary is 32-bit.
//
BOOLEAN Is32Bit;
//
// Patcher context is contained within a kernel collection.
//
BOOLEAN IsKernelCollection;
BOOLEAN IsKernelCollection;
} PATCHER_CONTEXT;
//
......@@ -411,6 +420,10 @@ typedef struct {
//
UINT32 KernelVersion;
//
// System is booting in 32-bit mode.
//
BOOLEAN Is32Bit;
//
// Flag to indicate if above list is valid. List is built during the first read from SLE.
//
BOOLEAN BuiltInKextsValid;
......@@ -772,6 +785,7 @@ PrelinkedInjectComplete (
@param[in] InfoPlistSize Kext Info.plist size.
@param[in] Executable Kext executable, optional.
@param[in] ExecutableSize Kext executable size, optional.
@param[in] Is32Bit TRUE to process 32-bit kext.
@return EFI_SUCCESS on success.
**/
......@@ -781,7 +795,8 @@ PrelinkedReserveKextSize (
IN OUT UINT32 *ReservedExeSize,
IN UINT32 InfoPlistSize,
IN UINT8 *Executable OPTIONAL,
IN UINT32 ExecutableSize OPTIONAL
IN UINT32 ExecutableSize OPTIONAL,
IN BOOLEAN Is32Bit
);
/**
......@@ -843,6 +858,20 @@ PrelinkedContextApplyQuirk (
IN UINT32 KernelVersion
);
/**
Block kext in prelinked.
@param[in,out] Context Prelinked context.
@param[in] Identifier Kext bundle identifier.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
PrelinkedContextBlock (
IN OUT PRELINKED_CONTEXT *Context,
IN CONST CHAR8 *Identifier
);
/**
Update Mach-O header with new commands.
......@@ -980,6 +1009,7 @@ PatcherInitContextFromMkext(
@param[in,out] Context Patcher context.
@param[in,out] Buffer Kernel buffer (could be prelinked).
@param[in] BufferSize Kernel buffer size.
@param[in] Is32Bit TRUE to use 32-bit.
@return EFI_SUCCESS on success.
**/
......@@ -987,7 +1017,8 @@ EFI_STATUS
PatcherInitContextFromBuffer (
IN OUT PATCHER_CONTEXT *Context,
IN OUT UINT8 *Buffer,
IN UINT32 BufferSize
IN UINT32 BufferSize,
IN BOOLEAN Use32Bit
);
/**
......@@ -1032,13 +1063,32 @@ PatcherBlockKext (
IN OUT PATCHER_CONTEXT *Context
);
/**
Find kmod address.
@param[in] ExecutableContext Mach-O context.
@param[in] LoadAddress Load address.
@param[in] Size Executable size.
@param[out] Kmod Pointer to kmod.
@return TRUE on success.
**/
BOOLEAN
KextFindKmodAddress (
IN OC_MACHO_CONTEXT *ExecutableContext,
IN UINT64 LoadAddress,
IN UINT32 Size,
OUT UINT64 *Kmod
);
/**
Apply modification to CPUID 1.
@param Patcher Patcher context.
@param CpuInfo CPU information.
@param Data 4 32-bit integers with CPUID data.
@param DataMask 4 32-bit integers with CPUID enabled overrides data.
@param Patcher Patcher context.
@param CpuInfo CPU information.
@param Data 4 32-bit integers with CPUID data.
@param DataMask 4 32-bit integers with CPUID enabled overrides data.
@param KernelVersion Curent kernel version.
@return EFI_SUCCESS on success.
**/
......@@ -1047,7 +1097,8 @@ PatchKernelCpuId (
IN OUT PATCHER_CONTEXT *Patcher,
IN OC_CPU_INFO *CpuInfo,
IN UINT32 *Data,
IN UINT32 *DataMask
IN UINT32 *DataMask,
IN UINT32 KernelVersion
);
/**
......@@ -1058,6 +1109,7 @@ PatchKernelCpuId (
@param[in] FileName Extensions directory filename.
@param[in] ExtensionsDir Extensions directory EFI_FILE_PROTOCOL.
@param[in] KernelVersion Current kernel version.
@param[in] Is32Bit TRUE if booting in 32-bit kernel mode.
@return EFI_SUCCESS on success.
**/
......@@ -1066,7 +1118,8 @@ CachelessContextInit (
IN OUT CACHELESS_CONTEXT *Context,
IN CONST CHAR16 *FileName,
IN EFI_FILE_PROTOCOL *ExtensionsDir,
IN UINT32 KernelVersion
IN UINT32 KernelVersion,
IN BOOLEAN Is32Bit
);
/**
......@@ -1145,6 +1198,20 @@ CachelessContextAddQuirk (
IN KERNEL_QUIRK_NAME Quirk
);
/**
Add block request to cacheless context to be applied later on.
@param[in,out] Context Cacheless context.
@param[in] Identifier Kext bundle identifier.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
CachelessContextBlock (
IN OUT CACHELESS_CONTEXT *Context,
IN CONST CHAR8 *Identifier
);
/**
Creates virtual directory overlay EFI_FILE_PROTOCOL from cacheless context.
......@@ -1275,6 +1342,7 @@ MkextContextFree (
@param[in] InfoPlistSize Kext Info.plist size.
@param[in] Executable Kext executable, optional.
@param[in] ExecutableSize Kext executable size, optional.
@param[in] Is32Bit TRUE to process 32-bit kext.
@return EFI_SUCCESS on success.
**/
......@@ -1283,8 +1351,9 @@ MkextReserveKextSize (
IN OUT UINT32 *ReservedInfoSize,
IN OUT UINT32 *ReservedExeSize,
IN UINT32 InfoPlistSize,
IN UINT8 *Executable,
IN UINT32 ExecutableSize OPTIONAL
IN UINT8 *Executable OPTIONAL,
IN UINT32 ExecutableSize OPTIONAL,
IN BOOLEAN Is32Bit
);
/**
......@@ -1344,6 +1413,20 @@ MkextContextApplyQuirk (
IN UINT32 KernelVersion
);
/**
Block kext in mkext.
@param[in,out] Context Mkext context.
@param[in] Identifier Kext bundle identifier.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
MkextContextBlock (
IN OUT MKEXT_CONTEXT *Context,
IN CONST CHAR8 *Identifier
);
/**
Refresh plist and checksum after kext
injection and/or patching.
......
......@@ -155,7 +155,8 @@ OcKernelBlockKexts (
IN OC_GLOBAL_CONFIG *Config,
IN UINT32 DarwinVersion,
IN BOOLEAN Is32Bit,
IN PRELINKED_CONTEXT *Context
IN KERNEL_CACHE_TYPE CacheType,
IN VOID *Context
);
/**
......
......@@ -858,8 +858,8 @@ typedef struct {
UINT32 Size; ///< size in bytes of this section
UINT32 Offset; ///< file offset of this section
UINT32 Alignment; ///< section alignment (power of 2)
UINT32 RelocationEntriesOffset; ///< file offset of relocation entries
UINT32 NumRelocationEntries; ///< number of relocation entries
UINT32 RelocationsOffset; ///< file offset of relocation entries
UINT32 NumRelocations; ///< number of relocation entries
UINT32 Flags; ///< flags (section type and attributes)
UINT32 Reserved1; ///< reserved (for offset or index)
UINT32 Reserved2; ///< reserved (for count or sizeof)
......@@ -883,6 +883,11 @@ typedef struct {
UINT32 Reserved3; ///< reserved
} MACH_SECTION_64;
typedef union {
MACH_SECTION Section32;
MACH_SECTION_64 Section64;
} MACH_SECTION_ANY;
#define NEXT_MACH_SEGMENT(Segment) \
(MACH_SEGMENT_COMMAND *)((UINTN)(Segment) + (Segment)->Command.Size)
......@@ -939,6 +944,11 @@ typedef struct {
MACH_SECTION_64 Sections[];
} MACH_SEGMENT_COMMAND_64;
typedef union {
MACH_SEGMENT_COMMAND Segment32;
MACH_SEGMENT_COMMAND_64 Segment64;
} MACH_SEGMENT_COMMAND_ANY;
///
/// A fixed virtual shared library (filetype == MH_FVMLIB in the mach header)
/// contains a fvmlib_command (cmd == LC_IDFVMLIB) to identify the library.
......@@ -2109,6 +2119,11 @@ typedef struct {
UINT64 Value; ///< value of this symbol (or stab offset)
} MACH_NLIST_64;
typedef union {
MACH_NLIST Symbol32;
MACH_NLIST_64 Symbol64;
} MACH_NLIST_ANY;
//
// Symbols with a index into the string table of zero (n_un.n_strx == 0) are
// defined to have a null, "", name. Therefore all string indexes to non null
......
......@@ -586,6 +586,35 @@ ScanDependencies (
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
InternalAddPatchedKext (
IN OUT CACHELESS_CONTEXT *Context,
IN CONST CHAR8 *Identifier,
OUT PATCHED_KEXT **Kext
)
{
PATCHED_KEXT *PatchedKext;
PatchedKext = AllocateZeroPool (sizeof (*PatchedKext));
if (PatchedKext == NULL) {
return EFI_OUT_OF_RESOURCES;
}
PatchedKext->Signature = PATCHED_KEXT_SIGNATURE;
PatchedKext->Identifier = AllocateCopyPool (AsciiStrSize (Identifier), Identifier);
if (PatchedKext->Identifier == NULL) {
FreePool (PatchedKext);
return EFI_OUT_OF_RESOURCES;
}
InitializeListHead (&PatchedKext->Patches);
InsertTailList (&Context->PatchedKexts, &PatchedKext->Link);
*Kext = PatchedKext;
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
InternalAddKextPatch (
......@@ -595,6 +624,7 @@ InternalAddKextPatch (
IN KERNEL_QUIRK_NAME QuirkName
)
{
EFI_STATUS Status;
PATCHED_KEXT *PatchedKext;
KEXT_PATCH *KextPatch;
KERNEL_QUIRK *KernelQuirk;
......@@ -611,20 +641,10 @@ InternalAddKextPatch (
//
PatchedKext = LookupPatchedKextForIdentifier (Context, Identifier);
if (PatchedKext == NULL) {
PatchedKext = AllocateZeroPool (sizeof (*PatchedKext));
if (PatchedKext == NULL) {
return EFI_OUT_OF_RESOURCES;
}
PatchedKext->Signature = PATCHED_KEXT_SIGNATURE;
PatchedKext->Identifier = AllocateCopyPool (AsciiStrSize (Identifier), Identifier);
if (PatchedKext->Identifier == NULL) {
FreePool (PatchedKext);
return EFI_OUT_OF_RESOURCES;
Status = InternalAddPatchedKext (Context, Identifier, &PatchedKext);
if (EFI_ERROR (Status)) {
return Status;
}
InitializeListHead (&PatchedKext->Patches);
InsertTailList (&Context->PatchedKexts, &PatchedKext->Link);
}
//
......@@ -657,7 +677,8 @@ CachelessContextInit (
IN OUT CACHELESS_CONTEXT *Context,
IN CONST CHAR16 *FileName,
IN EFI_FILE_PROTOCOL *ExtensionsDir,
IN UINT32 KernelVersion
IN UINT32 KernelVersion,
IN BOOLEAN Is32Bit
)
{
ASSERT (Context != NULL);
......@@ -669,6 +690,7 @@ CachelessContextInit (
Context->ExtensionsDir = ExtensionsDir;
Context->ExtensionsDirFileName = FileName;
Context->KernelVersion = KernelVersion;
Context->Is32Bit = Is32Bit;
InitializeListHead (&Context->InjectedKexts);
InitializeListHead (&Context->InjectedDependencies);
......@@ -986,6 +1008,31 @@ CachelessContextAddQuirk (
return InternalAddKextPatch (Context, NULL, NULL, Quirk);
}
EFI_STATUS
CachelessContextBlock (
IN OUT CACHELESS_CONTEXT *Context,
IN CONST CHAR8 *Identifier
)
{
EFI_STATUS Status;
PATCHED_KEXT *PatchedKext;
//
// Check if bundle is already present. If not, add to list.
//
PatchedKext = LookupPatchedKextForIdentifier (Context, Identifier);
if (PatchedKext == NULL) {
Status = InternalAddPatchedKext (Context, Identifier, &PatchedKext);
if (EFI_ERROR (Status)) {
return Status;
}
}
PatchedKext->Block = TRUE;
return EFI_SUCCESS;
}
EFI_STATUS
CachelessContextOverlayExtensionsDir (
IN OUT CACHELESS_CONTEXT *Context,
......@@ -1439,7 +1486,7 @@ CachelessContextHookBuiltin (
return Status;
}
Status = PatcherInitContextFromBuffer (&Patcher, Buffer, BufferSize);
Status = PatcherInitContextFromBuffer (&Patcher, Buffer, BufferSize, Context->Is32Bit);
if (EFI_ERROR (Status)) {
FreePool (Buffer);
return Status;
......@@ -1456,7 +1503,7 @@ CachelessContextHookBuiltin (
Status = KernelApplyQuirk (KextPatch->QuirkName, &Patcher, Context->KernelVersion);
DEBUG ((
EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
"OCAK: Kernel quirk result for %a (%u) - %r\n",
"OCAK: Cacheless kernel quirk result for %a (%u) - %r\n",
PatchedKext->Identifier,
KextPatch->QuirkName,
Status
......@@ -1465,7 +1512,7 @@ CachelessContextHookBuiltin (
Status = PatcherApplyGenericPatch (&Patcher, &KextPatch->Patch);
DEBUG ((
EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
"OCAK: Kext patcher result for %a (%a) - %r\n",
"OCAK: Cacheless patcher result for %a (%a) - %r\n",
PatchedKext->Identifier,
KextPatch->Patch.Comment,
Status
......@@ -1475,6 +1522,20 @@ CachelessContextHookBuiltin (
KextLink = GetNextNode (&PatchedKext->Patches, KextLink);
}
//
// Block kext if requested.
//
if (PatchedKext->Block) {
Status = PatcherBlockKext (&Patcher);
DEBUG ((
EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
"OCAK: Cacheless blocker result for %a (%a) - %r\n",
PatchedKext->Identifier,
KextPatch->Patch.Comment,
Status
));
}
//
// Virtualize patched binary.
//
......
......@@ -135,6 +135,10 @@ typedef struct {
// List of patches to apply.
//
LIST_ENTRY Patches;
//
// Block kext.
//
BOOLEAN Block;
} PATCHED_KEXT;
//
......
此差异已折叠。
......@@ -242,7 +242,7 @@ KcRebuildMachHeader (
// hardware reset (like on iOS) and they now really try to require W^X:
// https://developer.apple.com/videos/play/wwdc2020/10686/
//
if (!MachoMergeSegments64 (&Context->PrelinkedMachContext, KC_REGION_SEGMENT_PREFIX)) {
if (!MachoMergeSegments (&Context->PrelinkedMachContext, KC_REGION_SEGMENT_PREFIX)) {
DEBUG ((DEBUG_INFO, "OCAK: Segment expansion failure\n"));
return EFI_UNSUPPORTED;
}
......@@ -316,7 +316,7 @@ KcInitKextFixupChains (
"Alignment is not guaranteed."
);
DyldChainedFixups = (CONST MACH_LINKEDIT_DATA_COMMAND *) MachoGetNextCommand64 (
DyldChainedFixups = (CONST MACH_LINKEDIT_DATA_COMMAND *) MachoGetNextCommand (
&Context->PrelinkedMachContext,
MACH_LOAD_COMMAND_DYLD_CHAINED_FIXUPS,
NULL
......@@ -583,7 +583,7 @@ KcKextIndexFixups (
// re-initialisation in mind. We really don't want to sanitise everything
// again, so avoid the dedicated API for now.
//
DySymtab = (MACH_DYSYMTAB_COMMAND *) MachoGetNextCommand64 (
DySymtab = (MACH_DYSYMTAB_COMMAND *) MachoGetNextCommand (
MachContext,
MACH_LOAD_COMMAND_DYSYMTAB,
NULL
......
......@@ -27,6 +27,76 @@
#include "MkextInternal.h"
#include "PrelinkedInternal.h"
STATIC
BOOLEAN
GetTextBaseOffset (
IN OC_MACHO_CONTEXT *ExecutableContext,
OUT UINT64 *Address,
OUT UINT64 *Offset
)
{
MACH_SEGMENT_COMMAND *Segment32;
MACH_SECTION *Section32;
MACH_SEGMENT_COMMAND_64 *Segment64;
UINT64 VirtualAddress;
UINT64 FileOffset;
//
// 32-bit can be of type MH_OBJECT, which has all sections in a single unnamed segment.
// We'll fallback to that if there is no __TEXT segment.
//
if (ExecutableContext->Is32Bit) {
Segment32 = MachoGetNextSegment32 (ExecutableContext, NULL);
if (Segment32 == NULL) {
return FALSE;
}
if (AsciiStrCmp (Segment32->SegmentName, "") == 0) {
Section32 = MachoGetSectionByName32 (
ExecutableContext,
Segment32,
"__text"
);
if (Section32 == NULL) {
return FALSE;
}
VirtualAddress = Section32->Address;
FileOffset = Section32->Offset;
} else {
Segment32 = MachoGetSegmentByName32 (
ExecutableContext,
"__TEXT"
);
if (Segment32 == NULL || Segment32->VirtualAddress < Segment32->FileOffset) {
return FALSE;
}
VirtualAddress = Segment32->VirtualAddress;
FileOffset = Segment32->FileOffset;
}
} else {
Segment64 = MachoGetSegmentByName64 (
ExecutableContext,
"__TEXT"
);
if (Segment64 == NULL || Segment64->VirtualAddress < Segment64->FileOffset) {
return FALSE;
}
VirtualAddress = Segment64->VirtualAddress;
FileOffset = Segment64->FileOffset;
}
*Address = VirtualAddress;
*Offset = FileOffset;
return TRUE;
}
EFI_STATUS
PatcherInitContextFromPrelinked (
IN OUT PATCHER_CONTEXT *Context,
......@@ -59,19 +129,22 @@ PatcherInitContextFromMkext(
return EFI_NOT_FOUND;
}
return PatcherInitContextFromBuffer (Context, &Mkext->Mkext[Kext->BinaryOffset], Kext->BinarySize);
return PatcherInitContextFromBuffer (Context, &Mkext->Mkext[Kext->BinaryOffset], Kext->BinarySize, Mkext->Is32Bit);
}
EFI_STATUS
PatcherInitContextFromBuffer (
IN OUT PATCHER_CONTEXT *Context,
IN OUT UINT8 *Buffer,
IN UINT32 BufferSize
IN UINT32 BufferSize,
IN BOOLEAN Is32Bit
)
{
EFI_STATUS Status;
OC_MACHO_CONTEXT InnerContext;
MACH_SEGMENT_COMMAND_64 *Segment;
EFI_STATUS Status;
OC_MACHO_CONTEXT InnerContext;
UINT64 VirtualAddress;
UINT64 FileOffset;
ASSERT (Context != NULL);
ASSERT (Buffer != NULL);
......@@ -84,36 +157,58 @@ PatcherInitContextFromBuffer (
// and request PRELINK_KERNEL_IDENTIFIER.
//
if (!MachoInitializeContext (&Context->MachContext, Buffer, BufferSize, 0)) {
DEBUG ((DEBUG_INFO, "OCAK: Patcher init from buffer %p %u has unsupported mach-o\n", Buffer, BufferSize));
if (!MachoInitializeContext (&Context->MachContext, Buffer, BufferSize, 0, Is32Bit)) {
DEBUG ((
DEBUG_INFO,
"OCAK: %a-bit patcher init from buffer %p %u has unsupported mach-o\n",
Is32Bit ? "32" : "64",
Buffer,
BufferSize
));
return EFI_INVALID_PARAMETER;
}
Segment = MachoGetSegmentByName64 (
&Context->MachContext,
"__TEXT"
);
if (Segment == NULL || Segment->VirtualAddress < Segment->FileOffset) {
if (!GetTextBaseOffset (&Context->MachContext, &VirtualAddress, &FileOffset)) {
return EFI_NOT_FOUND;
}
Context->VirtualBase = Segment->VirtualAddress - Segment->FileOffset;
Context->Is32Bit = Is32Bit;
Context->VirtualBase = VirtualAddress;
Context->FileOffset = FileOffset;
Context->VirtualKmod = 0;
Context->KxldState = NULL;
Context->KxldStateSize = 0;
Context->IsKernelCollection = FALSE;
Status = InternalConnectExternalSymtab (
KextFindKmodAddress (
&Context->MachContext,
&InnerContext,
Buffer,
0,
BufferSize,
NULL
&Context->VirtualKmod
);
if (EFI_ERROR (Status)) {
return Status;
if (!Context->Is32Bit) {
Status = InternalConnectExternalSymtab (
&Context->MachContext,
&InnerContext,
Buffer,
BufferSize,
NULL
);
if (EFI_ERROR (Status)) {
return Status;
}
}
DEBUG ((
DEBUG_VERBOSE,
"OCAK: %a-bit patcher base 0x%llX kmod 0x%llX file 0x%llX\n",
Is32Bit ? "32" : "64",
Context->VirtualBase,
Context->VirtualKmod,
Context->FileOffset
));
return EFI_SUCCESS;
}
......@@ -124,11 +219,11 @@ PatcherGetSymbolAddress (
IN OUT UINT8 **Address
)
{
MACH_NLIST_64 *Symbol;
CONST CHAR8 *SymbolName;
UINT64 SymbolAddress;
UINT32 Offset;
UINT32 Index;
MACH_NLIST_ANY *Symbol;
CONST CHAR8 *SymbolName;
UINT64 SymbolAddress;
UINT32 Offset;
UINT32 Index;
Index = 0;
Offset = 0;
......@@ -136,7 +231,7 @@ PatcherGetSymbolAddress (
//
// Try the usual way first via SYMTAB.
//
Symbol = MachoGetSymbolByIndex64 (&Context->MachContext, Index);
Symbol = MachoGetSymbolByIndex (&Context->MachContext, Index);
if (Symbol == NULL) {
//
// If we have KxldState, use it.
......@@ -150,8 +245,7 @@ PatcherGetSymbolAddress (
//
// If we have a symbol, get its ondisk offset.
//
if (SymbolAddress != 0
&& MachoSymbolGetDirectFileOffset64 (&Context->MachContext, SymbolAddress, &Offset, NULL)) {
if (SymbolAddress != 0 && MachoSymbolGetDirectFileOffset (&Context->MachContext, SymbolAddress, &Offset, NULL)) {
//
// Proceed to success.
//
......@@ -162,12 +256,12 @@ PatcherGetSymbolAddress (
return EFI_NOT_FOUND;
}
SymbolName = MachoGetSymbolName64 (&Context->MachContext, Symbol);
SymbolName = MachoGetSymbolName (&Context->MachContext, Symbol);
if (SymbolName != NULL && AsciiStrCmp (Name, SymbolName) == 0) {
//
// Once we have a symbol, get its ondisk offset.
//
if (MachoSymbolGetFileOffset64 (&Context->MachContext, Symbol, &Offset, NULL)) {
if (MachoSymbolGetFileOffset (&Context->MachContext, Symbol, &Offset, NULL)) {
//
// Proceed to success.
//
......@@ -180,7 +274,7 @@ PatcherGetSymbolAddress (
Index++;
}
*Address = (UINT8 *)MachoGetMachHeader64 (&Context->MachContext) + Offset;
*Address = (UINT8 *) MachoGetMachHeader (&Context->MachContext) + Offset;
return EFI_SUCCESS;
}
......@@ -195,28 +289,30 @@ PatcherApplyGenericPatch (
UINT32 Size;
UINT32 ReplaceCount;
Base = (UINT8 *)MachoGetMachHeader64 (&Context->MachContext);
Base = (UINT8 *) MachoGetMachHeader (&Context->MachContext);
Size = MachoGetFileSize (&Context->MachContext);
if (Patch->Base != NULL) {
Status = PatcherGetSymbolAddress (Context, Patch->Base, &Base);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_INFO,
"OCAK: %a base lookup failure %r\n",
"OCAK: %a-bit %a base lookup failure %r\n",
Context->Is32Bit ? "32" : "64",
Patch->Comment != NULL ? Patch->Comment : "Patch",
Status
));
return Status;
}
Size -= (UINT32)(Base - (UINT8 *)MachoGetMachHeader64 (&Context->MachContext));
Size -= (UINT32)(Base - (UINT8 *) MachoGetMachHeader (&Context->MachContext));
}
if (Patch->Find == NULL) {
if (Size < Patch->Size) {
DEBUG ((
DEBUG_INFO,
"OCAK: %a is borked, not found\n",
"OCAK: %a-bit %a is borked, not found\n",
Context->Is32Bit ? "32" : "64",
Patch->Comment != NULL ? Patch->Comment : "Patch"
));
return EFI_NOT_FOUND;
......@@ -243,7 +339,8 @@ PatcherApplyGenericPatch (
DEBUG ((
DEBUG_INFO,
"OCAK: %a replace count - %u\n",
"OCAK: %a-bit %a replace count - %u\n",
Context->Is32Bit ? "32" : "64",
Patch->Comment != NULL ? Patch->Comment : "Patch",
ReplaceCount
));
......@@ -251,7 +348,8 @@ PatcherApplyGenericPatch (
if (ReplaceCount > 0 && Patch->Count > 0 && ReplaceCount != Patch->Count) {
DEBUG ((
DEBUG_INFO,
"OCAK: %a performed only %u replacements out of %u\n",
"OCAK: %a-bit %a performed only %u replacements out of %u\n",
Context->Is32Bit ? "32" : "64",
Patch->Comment != NULL ? Patch->Comment : "Patch",
ReplaceCount,
Patch->Count
......@@ -270,11 +368,13 @@ PatcherBlockKext (
IN OUT PATCHER_CONTEXT *Context
)
{
UINT64 KmodOffset;
UINT64 StartAddr;
UINT64 TmpOffset;
KMOD_INFO_64_V1 *KmodInfo;
UINT8 *PatchAddr;
UINT8 *MachBase;
UINT32 MachSize;
UINT64 KmodOffset;
UINT64 StartAddr;
UINT64 TmpOffset;
UINT8 *KmodInfo;
UINT8 *PatchAddr;
//
// Kernel has 0 kmod.
......@@ -283,26 +383,47 @@ PatcherBlockKext (
return EFI_UNSUPPORTED;
}
MachBase = (UINT8 *) MachoGetMachHeader (&Context->MachContext);
MachSize = MachoGetFileSize (&Context->MachContext);
//
// Determine offset of kmod within file.
//
KmodOffset = Context->VirtualKmod - Context->VirtualBase;
KmodInfo = (KMOD_INFO_64_V1 *)((UINT8 *) MachoGetMachHeader64 (&Context->MachContext) + KmodOffset);
StartAddr = KmodInfo->StartAddr;
if (Context->IsKernelCollection) {
StartAddr = KcFixupValue (StartAddr, NULL);
if (OcOverflowAddU64 (KmodOffset, Context->FileOffset, &KmodOffset)
|| OcOverflowAddU64 (KmodOffset, Context->Is32Bit ? sizeof (KMOD_INFO_32_V1) : sizeof (KMOD_INFO_64_V1), &TmpOffset)
|| TmpOffset > MachSize) {
return EFI_INVALID_PARAMETER;
}
if (OcOverflowAddU64 (KmodOffset, sizeof (KMOD_INFO_64_V1), &TmpOffset)
|| TmpOffset > MachoGetFileSize (&Context->MachContext)
|| StartAddr == 0
|| Context->VirtualBase > StartAddr) {
KmodInfo = MachBase + KmodOffset;
if (Context->Is32Bit) {
StartAddr = ((KMOD_INFO_32_V1 *) KmodInfo)->StartAddr;
} else {
StartAddr = ((KMOD_INFO_64_V1 *) KmodInfo)->StartAddr;
if (Context->IsKernelCollection) {
StartAddr = KcFixupValue (StartAddr, NULL);
}
}
if (StartAddr == 0 || Context->VirtualBase > StartAddr) {
return EFI_INVALID_PARAMETER;
}
TmpOffset = StartAddr - Context->VirtualBase;
if (TmpOffset > MachoGetFileSize (&Context->MachContext) - 6) {
if (OcOverflowAddU64 (TmpOffset, Context->FileOffset, &TmpOffset)
|| TmpOffset > MachSize - 6) {
return EFI_BUFFER_TOO_SMALL;
}
PatchAddr = (UINT8 *)MachoGetMachHeader64 (&Context->MachContext) + TmpOffset;
DEBUG ((
DEBUG_VERBOSE,
"OCAK: %a-bit blocker start @ 0x%llX\n",
Context->Is32Bit ? "32" : "64",
TmpOffset
));
PatchAddr = MachBase + TmpOffset;
//
// mov eax, KMOD_RETURN_FAILURE
......@@ -317,3 +438,55 @@ PatcherBlockKext (
return EFI_SUCCESS;
}
BOOLEAN
KextFindKmodAddress (
IN OC_MACHO_CONTEXT *ExecutableContext,
IN UINT64 LoadAddress,
IN UINT32 Size,
OUT UINT64 *Kmod
)
{
BOOLEAN Is32Bit;
MACH_NLIST_ANY *Symbol;
CONST CHAR8 *SymbolName;
UINT64 Address;
UINT64 FileOffset;
UINT32 Index;
Is32Bit = ExecutableContext->Is32Bit;
Index = 0;
while (TRUE) {
Symbol = MachoGetSymbolByIndex (ExecutableContext, Index);
if (Symbol == NULL) {
*Kmod = 0;
return TRUE;
}
if (((Is32Bit ? Symbol->Symbol32.Type : Symbol->Symbol64.Type) & MACH_N_TYPE_STAB) == 0) {
SymbolName = MachoGetSymbolName (ExecutableContext, Symbol);
if (SymbolName && AsciiStrCmp (SymbolName, "_kmod_info") == 0) {
if (!MachoIsSymbolValueInRange (ExecutableContext, Symbol)) {
return FALSE;
}
break;
}
}
Index++;
}
if (!GetTextBaseOffset (ExecutableContext, &Address, &FileOffset)) {
return FALSE;
}
if (OcOverflowTriAddU64 (Address, LoadAddress, Is32Bit ? Symbol->Symbol32.Value : Symbol->Symbol64.Value, &Address)
|| Address > LoadAddress + Size - (Is32Bit ? sizeof (KMOD_INFO_32_V1) : sizeof (KMOD_INFO_64_V1))
|| (Is32Bit && Address > MAX_UINT32)) {
return FALSE;
}
*Kmod = Address;
return TRUE;
}
......@@ -588,7 +588,7 @@ InternalCalculateTargetsIntel64 (
// the originals patched and then updates the referencing reloc.
//
if ((Vtable != NULL) && MachoSymbolNameIsVtable64 (Name)) {
if ((Vtable != NULL) && MachoSymbolNameIsVtable (Name)) {
*Vtable = InternalGetOcVtableByName (Context, Kext, Name);
}
......@@ -746,7 +746,7 @@ InternalRelocateRelocationIntel64 (
return MAX_UINTN;
}
InstructionPtr = MachoGetFilePointerByAddress64 (
InstructionPtr = MachoGetFilePointerByAddress (
&Kext->Context.MachContext,
(RelocationBase + Address),
&MaxSize
......@@ -1312,7 +1312,7 @@ InternalPrelinkKext64 (
//
// Retrieve the symbol tables required for most following operations.
//
NumSymbols = MachoGetSymbolTable (
NumSymbols = MachoGetSymbolTable64 (
MachoContext,
&SymbolTable,
&StringTable,
......@@ -1373,7 +1373,7 @@ InternalPrelinkKext64 (
// Solve indirect symbols.
//
WeakTestValue = 0;
NumIndirectSymbols = MachoGetIndirectSymbolTable (
NumIndirectSymbols = MachoGetIndirectSymbolTable64 (
MachoContext,
&IndirectSymtab
);
......@@ -1657,7 +1657,7 @@ InternalPrelinkKext64 (
// Reinitialize the Mach-O context to account for the changed __LINKEDIT
// segment and file size.
//
if (!MachoInitializeContext (MachoContext, MachHeader, (SegmentOffset + SegmentSize), MachoContext->ContainerOffset)) {
if (!MachoInitializeContext64 (MachoContext, MachHeader, (SegmentOffset + SegmentSize), MachoContext->ContainerOffset)) {
//
// This should never failed under normal and abnormal conditions.
//
......
......@@ -1089,8 +1089,9 @@ MkextReserveKextSize (
IN OUT UINT32 *ReservedInfoSize,
IN OUT UINT32 *ReservedExeSize,
IN UINT32 InfoPlistSize,
IN UINT8 *Executable,
IN UINT32 ExecutableSize OPTIONAL
IN UINT8 *Executable OPTIONAL,
IN UINT32 ExecutableSize OPTIONAL,
IN BOOLEAN Is32Bit
)
{
OC_MACHO_CONTEXT Context;
......@@ -1102,11 +1103,11 @@ MkextReserveKextSize (
if (Executable != NULL) {
ASSERT (ExecutableSize > 0);
if (!MachoInitializeContext (&Context, Executable, ExecutableSize, 0)) {
if (!MachoInitializeContext (&Context, Executable, ExecutableSize, 0, Is32Bit)) {
return EFI_INVALID_PARAMETER;
}
ExecutableSize = MachoGetVmSize64 (&Context);
ExecutableSize = MachoGetVmSize (&Context);
if (ExecutableSize == 0) {
return EFI_INVALID_PARAMETER;
}
......@@ -1370,7 +1371,7 @@ MkextContextApplyPatch (
Status = PatcherInitContextFromMkext (&Patcher, Context, Identifier);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to find %a - %r\n", Identifier, Status));
DEBUG ((DEBUG_INFO, "OCAK: Failed to mkext find %a - %r\n", Identifier, Status));
return Status;
}
......@@ -1403,7 +1404,27 @@ MkextContextApplyQuirk (
//
DEBUG ((DEBUG_INFO, "OCAK: Failed to mkext find %a - %r\n", KernelQuirk->Identifier, Status));
return KernelQuirk->PatchFunction (NULL, KernelVersion);
}
EFI_STATUS
MkextContextBlock (
IN OUT MKEXT_CONTEXT *Context,
IN CONST CHAR8 *Identifier
)
{
EFI_STATUS Status;
PATCHER_CONTEXT Patcher;
ASSERT (Context != NULL);
ASSERT (Identifier != NULL);
Status = PatcherInitContextFromMkext (&Patcher, Context, Identifier);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to mkext find %a - %r\n", Identifier, Status));
return Status;
}
return PatcherBlockKext (&Patcher);
}
EFI_STATUS
......
......@@ -42,6 +42,7 @@
Vtables.c
CachelessContext.c
MkextContext.c
CpuidPatches.c
[Packages]
MdePkg/MdePkg.dec
......
......@@ -95,57 +95,6 @@ PrelinkedFindLastLoadAddress (
return LoadAddress;
}
STATIC
BOOLEAN
PrelinkedFindKmodAddress (
IN OC_MACHO_CONTEXT *ExecutableContext,
IN UINT64 LoadAddress,
IN UINT32 Size,
OUT UINT64 *Kmod
)
{
MACH_NLIST_64 *Symbol;
CONST CHAR8 *SymbolName;
MACH_SEGMENT_COMMAND_64 *TextSegment;
UINT64 Address;
UINT32 Index;
Index = 0;
while (TRUE) {
Symbol = MachoGetSymbolByIndex64 (ExecutableContext, Index);
if (Symbol == NULL) {
*Kmod = 0;
return TRUE;
}
if ((Symbol->Type & MACH_N_TYPE_STAB) == 0) {
SymbolName = MachoGetSymbolName64 (ExecutableContext, Symbol);
if (SymbolName && AsciiStrCmp (SymbolName, "_kmod_info") == 0) {
if (!MachoIsSymbolValueInRange64 (ExecutableContext, Symbol)) {
return FALSE;
}
break;
}
}
Index++;
}
TextSegment = MachoGetSegmentByName64 (ExecutableContext, "__TEXT");
if (TextSegment == NULL || TextSegment->FileOffset > TextSegment->VirtualAddress) {
return FALSE;
}
Address = TextSegment->VirtualAddress - TextSegment->FileOffset;
if (OcOverflowTriAddU64 (Address, LoadAddress, Symbol->Value, &Address)
|| Address > LoadAddress + Size - sizeof (KMOD_INFO_64_V1)) {
return FALSE;
}
*Kmod = Address;
return TRUE;
}
STATIC
EFI_STATUS
PrelinkedGetSegmentsFromMacho (
......@@ -222,7 +171,7 @@ InternalConnectExternalSymtab (
return EFI_INVALID_PARAMETER;
}
if (!MachoInitializeContext (
if (!MachoInitializeContext64 (
InnerContext,
&Buffer[Segment->FileOffset],
(UINT32) (BufferSize - Segment->FileOffset),
......@@ -236,7 +185,7 @@ InternalConnectExternalSymtab (
return EFI_INVALID_PARAMETER;
}
if (!MachoInitialiseSymtabsExternal64 (Context, InnerContext)) {
if (!MachoInitialiseSymtabsExternal (Context, InnerContext)) {
DEBUG ((
DEBUG_INFO,
"OCAK: KC symtab failed getting symtab from inner %Lx %x\n",
......@@ -292,7 +241,7 @@ PrelinkedContextInit (
//
// Initialise primary context.
//
if (!MachoInitializeContext (&Context->PrelinkedMachContext, Prelinked, PrelinkedSize, 0)) {
if (!MachoInitializeContext64 (&Context->PrelinkedMachContext, Prelinked, PrelinkedSize, 0)) {
return EFI_INVALID_PARAMETER;
}
......@@ -857,8 +806,9 @@ PrelinkedReserveKextSize (
IN OUT UINT32 *ReservedInfoSize,
IN OUT UINT32 *ReservedExeSize,
IN UINT32 InfoPlistSize,
IN UINT8 *Executable,
IN UINT32 ExecutableSize OPTIONAL
IN UINT8 *Executable OPTIONAL,
IN UINT32 ExecutableSize OPTIONAL,
IN BOOLEAN Is32Bit
)
{
OC_MACHO_CONTEXT Context;
......@@ -874,11 +824,11 @@ PrelinkedReserveKextSize (
if (Executable != NULL) {
ASSERT (ExecutableSize > 0);
if (!MachoInitializeContext (&Context, Executable, ExecutableSize, 0)) {
if (!MachoInitializeContext (&Context, Executable, ExecutableSize, 0, Is32Bit)) {
return EFI_INVALID_PARAMETER;
}
ExecutableSize = MachoGetVmSize64 (&Context);
ExecutableSize = MachoGetVmSize (&Context);
if (ExecutableSize == 0) {
return EFI_INVALID_PARAMETER;
}
......@@ -956,7 +906,7 @@ PrelinkedInjectKext (
//
if (Executable != NULL) {
ASSERT (ExecutableSize > 0);
if (!MachoInitializeContext (&ExecutableContext, (UINT8 *)Executable, ExecutableSize, 0)) {
if (!MachoInitializeContext64 (&ExecutableContext, (UINT8 *)Executable, ExecutableSize, 0)) {
DEBUG ((DEBUG_INFO, "OCAK: Injected kext %a/%a is not a supported executable\n", BundlePath, ExecutablePath));
return EFI_INVALID_PARAMETER;
}
......@@ -965,7 +915,7 @@ PrelinkedInjectKext (
//
KextOffset = Context->PrelinkedSize;
ExecutableSize = MachoExpandImage64 (
ExecutableSize = MachoExpandImage (
&ExecutableContext,
&Context->Prelinked[KextOffset],
Context->PrelinkedAllocSize - KextOffset,
......@@ -985,11 +935,11 @@ PrelinkedInjectKext (
AlignedExecutableSize - ExecutableSize
);
if (!MachoInitializeContext (&ExecutableContext, &Context->Prelinked[KextOffset], ExecutableSize, 0)) {
if (!MachoInitializeContext64 (&ExecutableContext, &Context->Prelinked[KextOffset], ExecutableSize, 0)) {
return EFI_INVALID_PARAMETER;
}
Result = PrelinkedFindKmodAddress (&ExecutableContext, Context->PrelinkedLastLoadAddress, ExecutableSize, &KmodAddress);
Result = KextFindKmodAddress (&ExecutableContext, Context->PrelinkedLastLoadAddress, ExecutableSize, &KmodAddress);
if (!Result) {
return EFI_INVALID_PARAMETER;
}
......@@ -1210,6 +1160,27 @@ PrelinkedContextApplyQuirk (
//
// It is up to the function to decide whether this is critical or not.
//
DEBUG ((DEBUG_INFO, "OCAK: Failed to find %a - %r\n", KernelQuirk->Identifier, Status));
DEBUG ((DEBUG_INFO, "OCAK: Failed to pk find %a - %r\n", KernelQuirk->Identifier, Status));
return KernelQuirk->PatchFunction (NULL, KernelVersion);
}
EFI_STATUS
PrelinkedContextBlock (
IN OUT PRELINKED_CONTEXT *Context,
IN CONST CHAR8 *Identifier
)
{
EFI_STATUS Status;
PATCHER_CONTEXT Patcher;
ASSERT (Context != NULL);
ASSERT (Identifier != NULL);
Status = PatcherInitContextFromPrelinked (&Patcher, Context, Identifier);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to pk find %a - %r\n", Identifier, Status));
return Status;
}
return PatcherBlockKext (&Patcher);
}
......@@ -216,7 +216,7 @@ InternalCreatePrelinkedKext (
if (Prelinked != NULL
&& HasExe
&& !MachoInitializeContext (&NewKext->Context.MachContext, &Prelinked->Prelinked[SourceBase], (UINT32)SourceSize, ContainerOffset)) {
&& !MachoInitializeContext64 (&NewKext->Context.MachContext, &Prelinked->Prelinked[SourceBase], (UINT32)SourceSize, ContainerOffset)) {
FreePool (NewKext);
return NULL;
}
......@@ -289,7 +289,7 @@ InternalScanCurrentPrelinkedKextLinkInfo (
}
if (Kext->SymbolTable == NULL && Kext->NumberOfSymbols == 0) {
Kext->NumberOfSymbols = MachoGetSymbolTable (
Kext->NumberOfSymbols = MachoGetSymbolTable64 (
&Kext->Context.MachContext,
&Kext->SymbolTable,
&Kext->StringTable,
......@@ -477,7 +477,7 @@ InternalScanBuildLinkedVtables (
// need to abort anyway when the value is out of its bounds, we can
// just locate it by address in the first place.
//
Tmp = MachoGetFilePointerByAddress64 (
Tmp = MachoGetFilePointerByAddress (
&Kext->Context.MachContext,
VtableLookups[Index].Vtable.Value,
&VtableMaxSize
......
......@@ -198,7 +198,7 @@ InternalPrepareCreateVtablesPrelinked64 (
++Index
) {
Symbol = &Kext->LinkedSymbolTable[Index];
if (MachoSymbolNameIsVtable64 (Symbol->Name)) {
if (MachoSymbolNameIsVtable (Symbol->Name)) {
//
// This seems to be valid for KC format as some symbols may be kernel imports?!
// Observed with IOACPIFamily when injecting VirtualSMC:
......@@ -285,7 +285,7 @@ InternalPatchVtableSymbol (
//
// 1) If the symbol is defined locally, do not patch
//
if (MachoSymbolIsLocalDefined (MachoContext, Symbol)) {
if (MachoSymbolIsLocalDefined64 (MachoContext, Symbol)) {
return TRUE;
}
......@@ -325,7 +325,7 @@ InternalPatchVtableSymbol (
// declared as part of the class and not inherited, which means we
// should not patch it.
//
if (!MachoSymbolIsDefined (Symbol)) {
if (!MachoSymbolIsDefined64 (Symbol)) {
ClassName = MachoGetClassNameFromVtableName (VtableName);
Success = MachoGetFunctionPrefixFromClassName (
......@@ -627,7 +627,7 @@ InternalPatchByVtables64 (
) {
Name = MachoGetSymbolName64 (MachoContext, Smcp);
if (((Smcp->Type & MACH_N_TYPE_STAB) == 0)
&& MachoSymbolNameIsSmcp64 (MachoContext, Name)) {
&& MachoSymbolNameIsSmcp (MachoContext, Name)) {
if (MaxSize < sizeof (*EntryWalker)) {
return FALSE;
}
......@@ -722,7 +722,7 @@ InternalPatchByVtables64 (
// number of vtables we're expecting, because every pointer will have a
// class vtable and a MetaClass vtable.
//
ASSERT (MachoSymbolNameIsSmcp64 (MachoContext, Name));
ASSERT (MachoSymbolNameIsSmcp (MachoContext, Name));
//
// Get the class name from the smc pointer
//
......@@ -815,7 +815,7 @@ InternalPatchByVtables64 (
return FALSE;
}
SymbolDummy = MachoGetLocalDefinedSymbolByName (
SymbolDummy = MachoGetLocalDefinedSymbolByName64 (
MachoContext,
FinalSymbolName
);
......
......@@ -38,14 +38,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#define VTABLE_HEADER_LEN_64 2U
#define VTABLE_HEADER_SIZE_64 (VTABLE_HEADER_LEN_64 * VTABLE_ENTRY_SIZE_64)
#define SYM_MAX_NAME_LEN 256U
/**
Returns whether Name is pure virtual.
@param[in] Name The name to evaluate.
**/
BOOLEAN
MachoSymbolNameIsPureVirtual (
IN CONST CHAR8 *Name
......@@ -55,12 +47,6 @@ MachoSymbolNameIsPureVirtual (
return (AsciiStrCmp (Name, CXX_PURE_VIRTUAL) == 0);
}
/**
Returns whether Name is a Padslot.
@param[in] Name The name to evaluate.
**/
BOOLEAN
MachoSymbolNameIsPadslot (
IN CONST CHAR8 *Name
......@@ -70,15 +56,8 @@ MachoSymbolNameIsPadslot (
return (AsciiStrStr (Name, RESERVED_TOKEN) != NULL);
}
/**
Returns whether SymbolName defines a Super Metaclass Pointer.
@param[in,out] Context Context of the Mach-O.
@param[in] SymbolName The symbol name to check.
**/
BOOLEAN
MachoSymbolNameIsSmcp64 (
MachoSymbolNameIsSmcp (
IN OUT OC_MACHO_CONTEXT *Context,
IN CONST CHAR8 *SymbolName
)
......@@ -104,15 +83,8 @@ MachoSymbolNameIsSmcp64 (
return TRUE;
}
/**
Returns whether SymbolName defines a Super Metaclass Pointer.
@param[in,out] Context Context of the Mach-O.
@param[in] SymbolName The symbol name to check.
**/
BOOLEAN
MachoSymbolNameIsMetaclassPointer64 (
MachoSymbolNameIsMetaclassPointer (
IN OUT OC_MACHO_CONTEXT *Context,
IN CONST CHAR8 *SymbolName
)
......@@ -138,17 +110,6 @@ MachoSymbolNameIsMetaclassPointer64 (
return TRUE;
}
/**
Retrieves the class name of a Super Meta Class Pointer.
@param[in,out] Context Context of the Mach-O.
@param[in] SmcpName SMCP Symbol name to get the class name of.
@param[in] ClassNameSize The size of ClassName.
@param[out] ClassName The output buffer for the class name.
@returns Whether the name has been retrieved successfully.
**/
BOOLEAN
MachoGetClassNameFromSuperMetaClassPointer (
IN OUT OC_MACHO_CONTEXT *Context,
......@@ -168,7 +129,7 @@ MachoGetClassNameFromSuperMetaClassPointer (
ASSERT (Context->StringTable != NULL);
ASSERT (MachoSymbolNameIsSmcp64 (Context, SmcpName));
ASSERT (MachoSymbolNameIsSmcp (Context, SmcpName));
PrefixSize = L_STR_LEN (OSOBJ_PREFIX);
SuffixSize = L_STR_LEN (SMCP_TOKEN);
......@@ -185,35 +146,19 @@ MachoGetClassNameFromSuperMetaClassPointer (
return TRUE;
}
/**
Retrieves the class name of a VTable.
@param[out] VtableName The VTable's name.
**/
CONST CHAR8 *
MachoGetClassNameFromVtableName (
IN CONST CHAR8 *VtableName
)
{
ASSERT (VtableName != NULL);
ASSERT (MachoSymbolNameIsVtable64 (VtableName));
ASSERT (MachoSymbolNameIsVtable (VtableName));
//
// As there is no suffix, just return a pointer from within VtableName.
//
return &VtableName[L_STR_LEN (VTABLE_PREFIX)];
}
/**
Retrieves the function prefix of a class name.
@param[in] ClassName The class name to evaluate.
@param[in] FunctionPrefixSize The size of FunctionPrefix.
@param[out] FunctionPrefix The output buffer for the function prefix.
@returns Whether the name has been retrieved successfully.
**/
BOOLEAN
MachoGetFunctionPrefixFromClassName (
IN CONST CHAR8 *ClassName,
......@@ -253,17 +198,6 @@ MachoGetFunctionPrefixFromClassName (
return TRUE;
}
/**
Retrieves the class name of a Meta Class Pointer.
@param[in,out] Context Context of the Mach-O.
@param[in] MetaClassName MCP Symbol name to get the class name of.
@param[in] ClassNameSize The size of ClassName.
@param[out] ClassName The output buffer for the class name.
@returns Whether the name has been retrieved successfully.
**/
BOOLEAN
MachoGetClassNameFromMetaClassPointer (
IN OUT OC_MACHO_CONTEXT *Context,
......@@ -283,7 +217,7 @@ MachoGetClassNameFromMetaClassPointer (
ASSERT (Context->StringTable != NULL);
ASSERT (MachoSymbolNameIsMetaclassPointer64 (Context, MetaClassName));
ASSERT (MachoSymbolNameIsMetaclassPointer (Context, MetaClassName));
PrefixSize = L_STR_LEN (OSOBJ_PREFIX);
SuffixSize = L_STR_LEN (METACLASS_TOKEN);
......@@ -299,16 +233,6 @@ MachoGetClassNameFromMetaClassPointer (
return TRUE;
}
/**
Retrieves the VTable name of a class name.
@param[in] ClassName Class name to get the VTable name of.
@param[in] VtableNameSize The size of VtableName.
@param[out] VtableName The output buffer for the VTable name.
@returns Whether the name has been retrieved successfully.
**/
BOOLEAN
MachoGetVtableNameFromClassName (
IN CONST CHAR8 *ClassName,
......@@ -349,16 +273,6 @@ MachoGetVtableNameFromClassName (
return TRUE;
}
/**
Retrieves the Meta VTable name of a class name.
@param[in] ClassName Class name to get the Meta VTable name of.
@param[in] VtableNameSize The size of VtableName.
@param[out] VtableName The output buffer for the VTable name.
@returns Whether the name has been retrieved successfully.
**/
BOOLEAN
MachoGetMetaVtableNameFromClassName (
IN CONST CHAR8 *ClassName,
......@@ -407,16 +321,6 @@ MachoGetMetaVtableNameFromClassName (
return TRUE;
}
/**
Retrieves the final symbol name of a class name.
@param[in] ClassName Class name to get the final symbol name of.
@param[in] FinalSymbolNameSize The size of FinalSymbolName.
@param[out] FinalSymbolName The output buffer for the final symbol name.
@returns Whether the name has been retrieved successfully.
**/
BOOLEAN
MachoGetFinalSymbolNameFromClassName (
IN CONST CHAR8 *ClassName,
......@@ -469,15 +373,8 @@ MachoGetFinalSymbolNameFromClassName (
return TRUE;
}
/**
Returns whether SymbolName defines a VTable.
@param[in,out] Context Context of the Mach-O.
@param[in] SymbolName The symbol name to check.
**/
BOOLEAN
MachoSymbolNameIsVtable64 (
MachoSymbolNameIsVtable (
IN CONST CHAR8 *SymbolName
)
{
......@@ -488,12 +385,6 @@ MachoSymbolNameIsVtable64 (
return AsciiStrnCmp (SymbolName, VTABLE_PREFIX, L_STR_LEN (VTABLE_PREFIX)) == 0;
}
/**
Returns whether the symbol name describes a C++ symbol.
@param[in] Name The name to evaluate.
**/
BOOLEAN
MachoSymbolNameIsCxx (
IN CONST CHAR8 *Name
......@@ -502,119 +393,3 @@ MachoSymbolNameIsCxx (
ASSERT (Name != NULL);
return AsciiStrnCmp (Name, CXX_PREFIX, L_STR_LEN (CXX_PREFIX)) == 0;
}
/**
Retrieves Metaclass symbol of a SMCP.
@param[in,out] Context Context of the Mach-O.
@param[in] Smcp The SMCP to evaluate.
@retval NULL NULL is returned on failure.
**/
MACH_NLIST_64 *
MachoGetMetaclassSymbolFromSmcpSymbol64 (
IN OUT OC_MACHO_CONTEXT *Context,
IN CONST MACH_NLIST_64 *Smcp
)
{
MACH_NLIST_64 *Symbol;
BOOLEAN Result;
ASSERT (Context != NULL);
ASSERT (Smcp != NULL);
Result = MachoGetSymbolByRelocationOffset64 (
Context,
Smcp->Value,
&Symbol
);
if (Result && (Symbol != NULL)) {
Result = MachoSymbolNameIsMetaclassPointer64 (
Context,
MachoGetSymbolName64 (Context, Symbol)
);
if (Result) {
return Symbol;
}
}
return NULL;
}
/**
Retrieves VTable and Meta VTable of a SMCP.
Logically matches XNU's get_vtable_syms_from_smcp.
@param[in,out] Context Context of the Mach-O.
@param[in] SmcpName SMCP Symbol mame to retrieve the VTables from.
@param[out] Vtable Output buffer for the VTable symbol pointer.
@param[out] MetaVtable Output buffer for the Meta VTable symbol pointer.
**/
BOOLEAN
MachoGetVtableSymbolsFromSmcp64 (
IN OUT OC_MACHO_CONTEXT *Context,
IN CONST CHAR8 *SmcpName,
OUT CONST MACH_NLIST_64 **Vtable,
OUT CONST MACH_NLIST_64 **MetaVtable
)
{
CHAR8 ClassName[SYM_MAX_NAME_LEN];
CHAR8 VtableName[SYM_MAX_NAME_LEN];
CHAR8 MetaVtableName[SYM_MAX_NAME_LEN];
BOOLEAN Result;
MACH_NLIST_64 *VtableSymbol;
MACH_NLIST_64 *MetaVtableSymbol;
ASSERT (Context != NULL);
ASSERT (SmcpName != NULL);
ASSERT (Vtable != NULL);
ASSERT (MetaVtable != NULL);
Result = MachoGetClassNameFromSuperMetaClassPointer (
Context,
SmcpName,
sizeof (ClassName),
ClassName
);
if (!Result) {
return FALSE;
}
Result = MachoGetVtableNameFromClassName (
ClassName,
sizeof (VtableName),
VtableName
);
if (!Result) {
return FALSE;
}
VtableSymbol = MachoGetLocalDefinedSymbolByName (Context, VtableName);
if (VtableSymbol == NULL) {
return FALSE;
}
Result = MachoGetMetaVtableNameFromClassName (
ClassName,
sizeof (MetaVtableName),
MetaVtableName
);
if (!Result) {
return FALSE;
}
MetaVtableSymbol = MachoGetLocalDefinedSymbolByName (
Context,
MetaVtableName
);
if (MetaVtableSymbol == NULL) {
return FALSE;
}
*Vtable = VtableSymbol;
*MetaVtable = MetaVtableSymbol;
return TRUE;
}
/** @file
Provides services for C++ symbols.
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 "MachoX.h"
MACH_NLIST_X *
MACH_X (MachoGetMetaclassSymbolFromSmcpSymbol) (
IN OUT OC_MACHO_CONTEXT *Context,
IN CONST MACH_NLIST_X *Smcp
)
{
MACH_NLIST_X *Symbol;
BOOLEAN Result;
ASSERT (Context != NULL);
ASSERT (Smcp != NULL);
MACH_ASSERT_X (Context);
Result = MACH_X (MachoGetSymbolByRelocationOffset) (
Context,
Smcp->Value,
&Symbol
);
if (Result && (Symbol != NULL)) {
Result = MachoSymbolNameIsMetaclassPointer (
Context,
MACH_X (MachoGetSymbolName) (Context, Symbol)
);
if (Result) {
return Symbol;
}
}
return NULL;
}
BOOLEAN
MACH_X (MachoGetVtableSymbolsFromSmcp) (
IN OUT OC_MACHO_CONTEXT *Context,
IN CONST CHAR8 *SmcpName,
OUT CONST MACH_NLIST_X **Vtable,
OUT CONST MACH_NLIST_X **MetaVtable
)
{
CHAR8 ClassName[SYM_MAX_NAME_LEN];
CHAR8 VtableName[SYM_MAX_NAME_LEN];
CHAR8 MetaVtableName[SYM_MAX_NAME_LEN];
BOOLEAN Result;
MACH_NLIST_X *VtableSymbol;
MACH_NLIST_X *MetaVtableSymbol;
ASSERT (Context != NULL);
ASSERT (SmcpName != NULL);
ASSERT (Vtable != NULL);
ASSERT (MetaVtable != NULL);
MACH_ASSERT_X (Context);
Result = MachoGetClassNameFromSuperMetaClassPointer (
Context,
SmcpName,
sizeof (ClassName),
ClassName
);
if (!Result) {
return FALSE;
}
Result = MachoGetVtableNameFromClassName (
ClassName,
sizeof (VtableName),
VtableName
);
if (!Result) {
return FALSE;
}
VtableSymbol = MACH_X (MachoGetLocalDefinedSymbolByName) (Context, VtableName);
if (VtableSymbol == NULL) {
return FALSE;
}
Result = MachoGetMetaVtableNameFromClassName (
ClassName,
sizeof (MetaVtableName),
MetaVtableName
);
if (!Result) {
return FALSE;
}
MetaVtableSymbol = MACH_X (MachoGetLocalDefinedSymbolByName) (
Context,
MetaVtableName
);
if (MetaVtableSymbol == NULL) {
return FALSE;
}
*Vtable = VtableSymbol;
*MetaVtable = MetaVtableSymbol;
return TRUE;
}
此差异已折叠。
此差异已折叠。
/**
32-bit Mach-O library functions layer.
Copyright (C) 2020, Goldfish64. 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.
**/
//
// Enable 32-bit mode for library functions.
//
#define MACHO_LIB_32
#include "CxxSymbolsX.h"
#include "HeaderX.h"
#include "SymbolsX.h"
/**
64-bit Mach-O library functions layer.
Copyright (C) 2020, Goldfish64. 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 "CxxSymbolsX.h"
#include "HeaderX.h"
#include "SymbolsX.h"
/**
Mach-O library functions layer.
Copyright (C) 2020, Goldfish64. 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.
**/
#ifndef MACHO_X_INTERNAL_H
#define MACHO_X_INTERNAL_H
#include <Uefi.h>
#include <IndustryStandard/AppleMachoImage.h>
#include <IndustryStandard/AppleFatBinaryImage.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/OcGuardLib.h>
#include <Library/OcMachoLib.h>
#include "OcMachoLibInternal.h"
//
// 32-bit functions
//
#ifdef MACHO_LIB_32
#define MACH_UINT_X UINT32
#define MACH_HEADER_X MACH_HEADER
#define MACH_SECTION_X MACH_SECTION
#define MACH_SEGMENT_COMMAND_X MACH_SEGMENT_COMMAND
#define MACH_NLIST_X MACH_NLIST
#define MACH_LOAD_COMMAND_SEGMENT_X MACH_LOAD_COMMAND_SEGMENT
#define MACH_X(a) a##32
#define MACH_ASSERT_X(a) ASSERT ((a)->Is32Bit)
#define MACH_X_TO_UINT32(a) (a)
//
// 64-bit functions
//
#else
#define MACH_UINT_X UINT64
#define MACH_HEADER_X MACH_HEADER_64
#define MACH_SECTION_X MACH_SECTION_64
#define MACH_SEGMENT_COMMAND_X MACH_SEGMENT_COMMAND_64
#define MACH_NLIST_X MACH_NLIST_64
#define MACH_LOAD_COMMAND_SEGMENT_X MACH_LOAD_COMMAND_SEGMENT_64
#define MACH_X(a) a##64
#define MACH_ASSERT_X(a) ASSERT (!(a)->Is32Bit)
#define MACH_X_TO_UINT32(a) (UINT32)(a)
#endif
#endif // MACHO_X_INTERNAL_H
......@@ -30,8 +30,14 @@
[Sources]
CxxSymbols.c
CxxSymbolsX.h
Fat.c
Header.c
HeaderX.h
OcMachoLibInternal.h
Macho32.c
Macho64.c
MachoX.h
Relocations.c
Symbols.c
SymbolsX.h
......@@ -19,6 +19,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/OcMachoLib.h>
#define SYM_MAX_NAME_LEN 256U
/**
Retrieves the SYMTAB command.
......@@ -27,7 +29,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
@retval NULL NULL is returned on failure.
**/
BOOLEAN
InternalRetrieveSymtabs64 (
InternalRetrieveSymtabs (
IN OUT OC_MACHO_CONTEXT *Context
);
......@@ -61,7 +63,21 @@ InternalGetLocalRelocationByOffset (
);
/**
Check symbol validity.
Check 32-bit symbol validity.
@param[in,out] Context Context of the Mach-O.
@param[in] Symbol Symbol from some table.
@retval TRUE on success.
**/
BOOLEAN
InternalSymbolIsSane32 (
IN OUT OC_MACHO_CONTEXT *Context,
IN CONST MACH_NLIST *Symbol
);
/**
Check 64-bit symbol validity.
@param[in,out] Context Context of the Mach-O.
@param[in] Symbol Symbol from some table.
......@@ -69,9 +85,205 @@ InternalGetLocalRelocationByOffset (
@retval TRUE on success.
**/
BOOLEAN
InternalSymbolIsSane (
InternalSymbolIsSane64 (
IN OUT OC_MACHO_CONTEXT *Context,
IN CONST MACH_NLIST_64 *Symbol
);
/**
Retrieves the Mach-O file offset of the address pointed to by a 32-bit Symbol.
@param[in,out] Context Context of the Mach-O.
@param[in] Address Virtual address to retrieve the offset of.
@param[out] FileOffset Pointer the file offset is returned into.
If FALSE is returned, the output is undefined.
@param[out] MaxSize Maximum data safely available from FileOffset.
@retval 0 0 is returned on failure.
**/
BOOLEAN
InternalMachoSymbolGetDirectFileOffset32 (
IN OUT OC_MACHO_CONTEXT *Context,
IN UINT32 Address,
OUT UINT32 *FileOffset,
OUT UINT32 *MaxSize OPTIONAL
);
/**
Retrieves the Mach-O file offset of the address pointed to by a 64-bit Symbol.
@param[in,out] Context Context of the Mach-O.
@param[in] Address Virtual address to retrieve the offset of.
@param[out] FileOffset Pointer the file offset is returned into.
If FALSE is returned, the output is undefined.
@param[out] MaxSize Maximum data safely available from FileOffset.
@retval 0 0 is returned on failure.
**/
BOOLEAN
InternalMachoSymbolGetDirectFileOffset64 (
IN OUT OC_MACHO_CONTEXT *Context,
IN UINT64 Address,
OUT UINT32 *FileOffset,
OUT UINT32 *MaxSize OPTIONAL
);
/**
Returns the 32-bit Mach-O's virtual address space size.
@param[out] Context Context of the Mach-O.
**/
UINT32
InternalMachoGetVmSize32 (
IN OUT OC_MACHO_CONTEXT *Context
);
/**
Returns the 64-bit Mach-O's virtual address space size.
@param[out] Context Context of the Mach-O.
**/
UINT32
InternalMachoGetVmSize64 (
IN OUT OC_MACHO_CONTEXT *Context
);
/**
Retrieves the next 32-bit Load Command of type LoadCommandType.
@param[in,out] Context Context of the Mach-O.
@param[in] LoadCommandType Type of the Load Command to retrieve.
@param[in] LoadCommand Previous Load Command.
If NULL, the first match is returned.
@retval NULL NULL is returned on failure.
**/
MACH_LOAD_COMMAND *
InternalMachoGetNextCommand32 (
IN OUT OC_MACHO_CONTEXT *Context,
IN MACH_LOAD_COMMAND_TYPE LoadCommandType,
IN CONST MACH_LOAD_COMMAND *LoadCommand OPTIONAL
);
/**
Retrieves the next 64-bit Load Command of type LoadCommandType.
@param[in,out] Context Context of the Mach-O.
@param[in] LoadCommandType Type of the Load Command to retrieve.
@param[in] LoadCommand Previous Load Command.
If NULL, the first match is returned.
@retval NULL NULL is returned on failure.
**/
MACH_LOAD_COMMAND *
InternalMachoGetNextCommand64 (
IN OUT OC_MACHO_CONTEXT *Context,
IN MACH_LOAD_COMMAND_TYPE LoadCommandType,
IN CONST MACH_LOAD_COMMAND *LoadCommand OPTIONAL
);
/**
Returns a pointer to the 32-bit Mach-O file at the specified virtual address.
@param[in,out] Context Context of the Mach-O.
@param[in] Address Virtual address to look up.
@param[out] MaxSize Maximum data safely available from FileOffset.
If NULL is returned, the output is undefined.
**/
VOID *
InternalMachoGetFilePointerByAddress32 (
IN OUT OC_MACHO_CONTEXT *Context,
IN UINT32 Address,
OUT UINT32 *MaxSize OPTIONAL
);
/**
Returns a pointer to the 64-bit Mach-O file at the specified virtual address.
@param[in,out] Context Context of the Mach-O.
@param[in] Address Virtual address to look up.
@param[out] MaxSize Maximum data safely available from FileOffset.
If NULL is returned, the output is undefined.
**/
VOID *
InternalMachoGetFilePointerByAddress64 (
IN OUT OC_MACHO_CONTEXT *Context,
IN UINT64 Address,
OUT UINT32 *MaxSize OPTIONAL
);
/**
Expand 32-bit Mach-O image to Destination (make segment file sizes equal to vm sizes).
@param[in] Context Context of the Mach-O.
@param[out] Destination Output buffer.
@param[in] DestinationSize Output buffer maximum size.
@param[in] Strip Output with stripped prelink commands.
@returns New image size or 0 on failure.
**/
UINT32
InternalMachoExpandImage32 (
IN OC_MACHO_CONTEXT *Context,
OUT UINT8 *Destination,
IN UINT32 DestinationSize,
IN BOOLEAN Strip
);
/**
Expand 64-bit Mach-O image to Destination (make segment file sizes equal to vm sizes).
@param[in] Context Context of the Mach-O.
@param[out] Destination Output buffer.
@param[in] DestinationSize Output buffer maximum size.
@param[in] Strip Output with stripped prelink commands.
@returns New image size or 0 on failure.
**/
UINT32
InternalMachoExpandImage64 (
IN OC_MACHO_CONTEXT *Context,
OUT UINT8 *Destination,
IN UINT32 DestinationSize,
IN BOOLEAN Strip
);
/**
Merge 32-bit Mach-O segments into one with lowest protection.
@param[in,out] Context Context of the Mach-O.
@param[in] Prefix Segment prefix to merge.
@retval TRUE on success
**/
BOOLEAN
InternalMachoMergeSegments32 (
IN OUT OC_MACHO_CONTEXT *Context,
IN CONST CHAR8 *Prefix
);
/**
Merge 64-bit Mach-O segments into one with lowest protection.
@param[in,out] Context Context of the Mach-O.
@param[in] Prefix Segment prefix to merge.
@retval TRUE on success
**/
BOOLEAN
InternalMachoMergeSegments64 (
IN OUT OC_MACHO_CONTEXT *Context,
IN CONST CHAR8 *Prefix
);
#endif // OC_MACHO_LIB_INTERNAL_H_
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -91,7 +91,8 @@ OcKernelApplyPatches (
Status = PatcherInitContextFromBuffer (
&KernelPatcher,
Kernel,
Size
Size,
Is32Bit
);
if (EFI_ERROR (Status)) {
......@@ -116,7 +117,8 @@ OcKernelApplyPatches (
if (AsciiStrCmp (Arch, Is32Bit ? "x86_64" : "i386") == 0) {
DEBUG ((
DEBUG_INFO,
"OC: Kernel patcher skips %a (%a) patch at %u due to arch %a != %a\n",
"OC: %a patcher skips %a (%a) patch at %u due to arch %a != %a\n",
PRINT_KERNEL_CACHE_TYPE (CacheType),
Target,
Comment,
Index,
......@@ -129,7 +131,8 @@ OcKernelApplyPatches (
if (!OcMatchDarwinVersion (DarwinVersion, MinKernel, MaxKernel)) {
DEBUG ((
DEBUG_INFO,
"OC: Kernel patcher skips %a (%a) patch at %u due to version %u <= %u <= %u\n",
"OC: %a patcher skips %a (%a) patch at %u due to version %u <= %u <= %u\n",
PRINT_KERNEL_CACHE_TYPE (CacheType),
Target,
Comment,
Index,
......@@ -198,7 +201,8 @@ OcKernelApplyPatches (
DEBUG ((
EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
"OC: Kernel patcher result %u for %a (%a) - %r\n",
"OC: %a patcher result %u for %a (%a) - %r\n",
PRINT_KERNEL_CACHE_TYPE (CacheType),
Index,
Target,
Comment,
......@@ -270,7 +274,8 @@ OcKernelApplyPatches (
&KernelPatcher,
CpuInfo,
Config->Kernel.Emulate.Cpuid1Data,
Config->Kernel.Emulate.Cpuid1Mask
Config->Kernel.Emulate.Cpuid1Mask,
DarwinVersion
);
}
......@@ -293,11 +298,11 @@ OcKernelBlockKexts (
IN OC_GLOBAL_CONFIG *Config,
IN UINT32 DarwinVersion,
IN BOOLEAN Is32Bit,
IN PRELINKED_CONTEXT *Context
IN KERNEL_CACHE_TYPE CacheType,
IN VOID *Context
)
{
EFI_STATUS Status;
PATCHER_CONTEXT Patcher;
UINT32 Index;
OC_KERNEL_BLOCK_ENTRY *Kext;
CONST CHAR8 *Target;
......@@ -322,7 +327,8 @@ OcKernelBlockKexts (
if (AsciiStrCmp (Arch, Is32Bit ? "x86_64" : "i386") == 0) {
DEBUG ((
DEBUG_INFO,
"OC: Prelink blocker skips %a (%a) block at %u due to arch %a != %a\n",
"OC: %a blocker skips %a (%a) block at %u due to arch %a != %a\n",
PRINT_KERNEL_CACHE_TYPE (CacheType),
Target,
Comment,
Index,
......@@ -335,7 +341,8 @@ OcKernelBlockKexts (
if (!OcMatchDarwinVersion (DarwinVersion, MinKernel, MaxKernel)) {
DEBUG ((
DEBUG_INFO,
"OC: Prelink blocker skips %a (%a) block at %u due to version %u <= %u <= %u\n",
"OC: %a blocker skips %a (%a) block at %u due to version %u <= %u <= %u\n",
PRINT_KERNEL_CACHE_TYPE (CacheType),
Target,
Comment,
Index,
......@@ -346,22 +353,19 @@ OcKernelBlockKexts (
continue;
}
Status = PatcherInitContextFromPrelinked (
&Patcher,
Context,
Target
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "OC: Prelink blocker %a (%a) init failure - %r\n", Target, Comment, Status));
continue;
if (CacheType == CacheTypeCacheless) {
Status = CachelessContextBlock (Context, Target);
} else if (CacheType == CacheTypeMkext) {
Status = MkextContextBlock (Context, Target);
} else if (CacheType == CacheTypePrelinked) {
Status = PrelinkedContextBlock (Context, Target);
}
Status = PatcherBlockKext (&Patcher);
DEBUG ((
EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
"OC: Prelink blocker %a (%a) - %r\n",
"OC: %a blocker result %u for %a (%a) - %r\n",
PRINT_KERNEL_CACHE_TYPE (CacheType),
Index,
Target,
Comment,
Status
......
......@@ -136,7 +136,7 @@ ifneq ($(STANDALONE),1)
#
# OcMachoLib targets.
#
OBJS += CxxSymbols.o Fat.o Header.o Symbols.o Relocations.o
OBJS += CxxSymbols.o Fat.o Header.o Macho32.o Macho64.o Relocations.o Symbols.o
#
# OcAppleKeysLib targets.
#
......
......@@ -393,7 +393,8 @@ ApplyKernelPatches (
Status = PatcherInitContextFromBuffer (
&Patcher,
Kernel,
Size
Size,
FALSE
);
if (!EFI_ERROR (Status)) {
......@@ -414,7 +415,8 @@ ApplyKernelPatches (
&Patcher,
&CpuInfo,
VirtualCpuid,
VirtualCpuidMask
VirtualCpuidMask,
KernelVersion
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "[FAIL] CPUID kernel patch - %r\n", Status));
......@@ -575,7 +577,8 @@ int wrap_main(int argc, char** argv) {
&ReservedExeSize,
TestPlistSize,
TestData,
TestDataSize
TestDataSize,
FALSE
);
free(TestData);
......@@ -636,7 +639,8 @@ int wrap_main(int argc, char** argv) {
Status = PatcherInitContextFromBuffer (
&Patcher,
Prelinked,
PrelinkedSize
PrelinkedSize,
FALSE
);
if (!EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "[OK] Patcher init success\n"));
......
......@@ -7,6 +7,7 @@ PROJECT = KextInject
PRODUCT = $(PROJECT)$(SUFFIX)
OBJS = $(PROJECT).o \
CommonPatches.o \
CpuidPatches.o \
KernelVersion.o \
KextPatcher.o \
KxldState.o \
......
......@@ -39,7 +39,7 @@ MACH_UUID_COMMAND Uuid;
static int FeedMacho(void *file, uint32_t size) {
OC_MACHO_CONTEXT Context;
if (!MachoInitializeContext (&Context, file, size, 0)) {
if (!MachoInitializeContext64 (&Context, file, size, 0)) {
return -1;
}
......@@ -51,7 +51,7 @@ static int FeedMacho(void *file, uint32_t size) {
code++;
}
MACH_UUID_COMMAND *Cmd = MachoGetUuid64(&Context);
MACH_UUID_COMMAND *Cmd = MachoGetUuid(&Context);
if (Cmd) {
memcpy(&Uuid, Cmd, sizeof(Uuid));
code++;
......@@ -86,13 +86,13 @@ static int FeedMacho(void *file, uint32_t size) {
(Indirect && !AsciiStrCmp (Indirect, "__hack"))) {
code++;
}
if (MachoSymbolIsSection (Symbol)) {
if (MachoSymbolIsSection64 (Symbol)) {
code++;
}
if (MachoSymbolIsDefined (Symbol)) {
if (MachoSymbolIsDefined64 (Symbol)) {
code++;
}
if (MachoSymbolIsLocalDefined (&Context, Symbol)) {
if (MachoSymbolIsLocalDefined64 (&Context, Symbol)) {
code++;
}
......@@ -113,21 +113,21 @@ static int FeedMacho(void *file, uint32_t size) {
code++;
}
if (MachoSymbolNameIsSmcp64 (&Context, MachoGetSymbolName64 (&Context, Symbol))) {
if (MachoSymbolNameIsSmcp (&Context, MachoGetSymbolName64 (&Context, Symbol))) {
code++;
}
if (MachoSymbolNameIsMetaclassPointer64 (&Context, MachoGetSymbolName64 (&Context, Symbol))) {
if (MachoSymbolNameIsMetaclassPointer (&Context, MachoGetSymbolName64 (&Context, Symbol))) {
code++;
}
char out[64];
if (MachoSymbolNameIsSmcp64 (&Context, MachoGetSymbolName64 (&Context, Symbol))
if (MachoSymbolNameIsSmcp (&Context, MachoGetSymbolName64 (&Context, Symbol))
&& MachoGetClassNameFromSuperMetaClassPointer (&Context, MachoGetSymbolName64 (&Context, Symbol), sizeof(out), out)) {
code++;
}
if (MachoSymbolNameIsVtable64 (MachoGetSymbolName64 (&Context, Symbol))) {
if (MachoSymbolNameIsVtable (MachoGetSymbolName64 (&Context, Symbol))) {
if (AsciiStrCmp(MachoGetClassNameFromVtableName (MachoGetSymbolName64 (&Context, Symbol)), "sym")) {
code++;
}
......@@ -138,7 +138,7 @@ static int FeedMacho(void *file, uint32_t size) {
code++;
}
if (MachoSymbolNameIsMetaclassPointer64 (&Context, MachoGetSymbolName64 (&Context, Symbol))
if (MachoSymbolNameIsMetaclassPointer (&Context, MachoGetSymbolName64 (&Context, Symbol))
&& MachoGetClassNameFromMetaClassPointer (&Context, MachoGetSymbolName64 (&Context, Symbol), sizeof(out), out)
&& !AsciiStrCmp("SomeReallyLongStringJustInCaseToCheckIt", out)) {
code++;
......@@ -185,20 +185,20 @@ static int FeedMacho(void *file, uint32_t size) {
MachoRelocateSymbol64 (&Context, 0x100000000, &SSSS);
}
Symbol = MachoGetLocalDefinedSymbolByName (&Context, "_Assert");
Symbol = MachoGetLocalDefinedSymbolByName64 (&Context, "_Assert");
if (Symbol) {
CONST CHAR8 *Indirect = MachoGetIndirectSymbolName64 (&Context, Symbol);
if (!AsciiStrCmp (MachoGetSymbolName64 (&Context, Symbol), "__hack") ||
(Indirect && !AsciiStrCmp (Indirect, "__hack"))) {
code++;
}
if (MachoSymbolIsSection (Symbol)) {
if (MachoSymbolIsSection64 (Symbol)) {
code++;
}
if (MachoSymbolIsDefined (Symbol)) {
if (MachoSymbolIsDefined64 (Symbol)) {
code++;
}
if (MachoSymbolIsLocalDefined (&Context, Symbol)) {
if (MachoSymbolIsLocalDefined64 (&Context, Symbol)) {
code++;
}
......@@ -218,22 +218,22 @@ static int FeedMacho(void *file, uint32_t size) {
code++;
}
if (MachoSymbolNameIsSmcp64 (&Context, MachoGetSymbolName64 (&Context, Symbol))) {
if (MachoSymbolNameIsSmcp (&Context, MachoGetSymbolName64 (&Context, Symbol))) {
code++;
}
if (MachoSymbolNameIsMetaclassPointer64 (&Context, MachoGetSymbolName64 (&Context, Symbol))) {
if (MachoSymbolNameIsMetaclassPointer (&Context, MachoGetSymbolName64 (&Context, Symbol))) {
code++;
}
char out[64];
if (MachoSymbolNameIsSmcp64 (&Context, MachoGetSymbolName64 (&Context, Symbol))
if (MachoSymbolNameIsSmcp (&Context, MachoGetSymbolName64 (&Context, Symbol))
&& MachoGetClassNameFromSuperMetaClassPointer (&Context, MachoGetSymbolName64 (&Context, Symbol), sizeof(out), out)
&& !AsciiStrCmp("SomeReallyLongStringJustInCaseToCheckIt", out)) {
code++;
}
if (MachoSymbolNameIsVtable64 (MachoGetSymbolName64 (&Context, Symbol))) {
if (MachoSymbolNameIsVtable (MachoGetSymbolName64 (&Context, Symbol))) {
if (AsciiStrCmp(MachoGetClassNameFromVtableName (MachoGetSymbolName64 (&Context, Symbol)), "sym")) {
code++;
}
......@@ -244,7 +244,7 @@ static int FeedMacho(void *file, uint32_t size) {
code++;
}
if (MachoSymbolNameIsMetaclassPointer64 (&Context, MachoGetSymbolName64 (&Context, Symbol))
if (MachoSymbolNameIsMetaclassPointer (&Context, MachoGetSymbolName64 (&Context, Symbol))
&& MachoGetClassNameFromMetaClassPointer (&Context, MachoGetSymbolName64 (&Context, Symbol), sizeof(out), out)
&& !AsciiStrCmp("SomeReallyLongStringJustInCaseToCheckIt", out)) {
code++;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册