OcMachoLib: Support KC Mach-Os

This commit is contained in:
Download-Fritz 2020-07-04 15:28:22 +02:00
parent 6fdd4a2834
commit 07b697d28d
10 changed files with 104 additions and 50 deletions

View File

@ -34,6 +34,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
typedef struct {
MACH_HEADER_64 *MachHeader;
UINT32 FileSize;
UINT32 ContainerOffset;
MACH_SYMTAB_COMMAND *Symtab;
MACH_NLIST_64 *SymbolTable;
CHAR8 *StringTable;
@ -46,9 +47,11 @@ typedef struct {
/**
Initializes a Mach-O Context.
@param[out] Context Mach-O Context to initialize.
@param[in] FileData Pointer to the file's data.
@param[in] FileSize File size of FileData.
@param[out] Context Mach-O Context to initialize.
@param[in] FileData Pointer to the file's expected Mach-O header.
@param[in] FileSize File size of FileData.
@param[in] ContainerOffset The amount of Bytes the Mach-O header is offset
from the base (container, e.g. KC) of the file.
@return Whether Context has been initialized successfully.
@ -57,7 +60,8 @@ BOOLEAN
MachoInitializeContext (
OUT OC_MACHO_CONTEXT *Context,
IN VOID *FileData,
IN UINT32 FileSize
IN UINT32 FileSize,
IN UINT32 ContainerOffset
);
/**

View File

@ -642,7 +642,8 @@ KcGetKextSize (
Result = MachoInitializeContext (
&KextContext,
Context->Prelinked + KextOffset,
Context->PrelinkedSize - KextOffset
Context->PrelinkedSize - KextOffset,
KextOffset
);
if (!Result) {
return 0;

View File

@ -64,7 +64,7 @@ PatcherInitContextFromBuffer (
// and request PRELINK_KERNEL_IDENTIFIER.
//
if (!MachoInitializeContext (&Context->MachContext, Buffer, BufferSize)) {
if (!MachoInitializeContext (&Context->MachContext, Buffer, BufferSize, 0)) {
return EFI_INVALID_PARAMETER;
}

View File

@ -1644,7 +1644,7 @@ InternalPrelinkKext64 (
// Reinitialize the Mach-O context to account for the changed __LINKEDIT
// segment and file size.
//
if (!MachoInitializeContext (MachoContext, MachHeader, (SegmentOffset + SegmentSize))) {
if (!MachoInitializeContext (MachoContext, MachHeader, (SegmentOffset + SegmentSize), MachoContext->ContainerOffset)) {
//
// This should never failed under normal and abnormal conditions.
//

View File

@ -224,7 +224,7 @@ PrelinkedContextInit (
//
// Initialise primary context.
//
if (!MachoInitializeContext (&Context->PrelinkedMachContext, Prelinked, PrelinkedSize)) {
if (!MachoInitializeContext (&Context->PrelinkedMachContext, Prelinked, PrelinkedSize, 0)) {
return EFI_INVALID_PARAMETER;
}
@ -249,7 +249,8 @@ PrelinkedContextInit (
if (!MachoInitializeContext (
&Context->InnerMachContext,
&Context->Prelinked[Segment->FileOffset],
(UINT32) (Context->PrelinkedSize - Segment->FileOffset))) {
(UINT32) (Context->PrelinkedSize - Segment->FileOffset),
(UINT32) Segment->FileOffset)) {
return EFI_INVALID_PARAMETER;
}
@ -679,7 +680,7 @@ PrelinkedReserveKextSize (
if (Executable != NULL) {
ASSERT (ExecutableSize > 0);
if (!MachoInitializeContext (&Context, Executable, ExecutableSize)) {
if (!MachoInitializeContext (&Context, Executable, ExecutableSize, 0)) {
return EFI_INVALID_PARAMETER;
}
@ -747,7 +748,7 @@ PrelinkedInjectKext (
//
if (Executable != NULL) {
ASSERT (ExecutableSize > 0);
if (!MachoInitializeContext (&ExecutableContext, (UINT8 *)Executable, ExecutableSize)) {
if (!MachoInitializeContext (&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;
}
@ -776,7 +777,7 @@ PrelinkedInjectKext (
AlignedExecutableSize - ExecutableSize
);
if (!MachoInitializeContext (&ExecutableContext, &Context->Prelinked[KextOffset], ExecutableSize)) {
if (!MachoInitializeContext (&ExecutableContext, &Context->Prelinked[KextOffset], ExecutableSize, 0)) {
return EFI_INVALID_PARAMETER;
}

View File

@ -56,6 +56,7 @@ InternalCreatePrelinkedKext (
UINT64 SourceSize;
UINT64 SourceEnd;
BOOLEAN Found;
UINT32 ContainerOffset;
KextIdentifier = NULL;
BundleLibraries = NULL;
@ -155,6 +156,11 @@ InternalCreatePrelinkedKext (
SourceEnd > Prelinked->PrelinkedSize) {
return NULL;
}
ContainerOffset = 0;
if (Prelinked->IsKernelCollection) {
ContainerOffset = (UINT32) SourceBase;
}
}
//
@ -166,7 +172,7 @@ InternalCreatePrelinkedKext (
}
if (Prelinked != NULL
&& !MachoInitializeContext (&NewKext->Context.MachContext, &Prelinked->Prelinked[SourceBase], (UINT32)SourceSize)) {
&& !MachoInitializeContext (&NewKext->Context.MachContext, &Prelinked->Prelinked[SourceBase], (UINT32)SourceSize, ContainerOffset)) {
FreePool (NewKext);
return NULL;
}

View File

@ -187,7 +187,8 @@ BOOLEAN
MachoInitializeContext (
OUT OC_MACHO_CONTEXT *Context,
IN VOID *FileData,
IN UINT32 FileSize
IN UINT32 FileSize,
IN UINT32 ContainerOffset
)
{
MACH_HEADER_64 *MachHeader;
@ -272,8 +273,9 @@ MachoInitializeContext (
ZeroMem (Context, sizeof (*Context));
Context->MachHeader = MachHeader;
Context->FileSize = FileSize;
Context->MachHeader = MachHeader;
Context->FileSize = FileSize;
Context->ContainerOffset = ContainerOffset;
return TRUE;
}
@ -485,10 +487,15 @@ InternalSectionIsSane (
}
if (Section->NumRelocations != 0) {
Result = OcOverflowMulAddU32 (
Result = OcOverflowSubU32 (
Section->RelocationsOffset,
Context->ContainerOffset,
&TopOffset32
);
Result |= OcOverflowMulAddU32 (
Section->NumRelocations,
sizeof (MACH_RELOCATION_INFO),
Section->RelocationsOffset,
TopOffset32,
&TopOffset32
);
if (Result || (TopOffset32 > Context->FileSize)) {
@ -642,11 +649,16 @@ MachoGetNextSegment64 (
return NULL;
}
Result = OcOverflowAddU64 (
Result = OcOverflowSubU64 (
NextSegment->FileOffset,
NextSegment->FileSize,
Context->ContainerOffset,
&TopOfSegment
);
Result |= OcOverflowAddU64 (
TopOfSegment,
NextSegment->FileSize,
&TopOfSegment
);
if (Result || (TopOfSegment > Context->FileSize)) {
return NULL;
}
@ -821,9 +833,14 @@ InternalInitialiseSymtabs64 (
UINTN MachoAddress;
CHAR8 *StringTable;
UINT32 FileSize;
UINT32 SymbolsOffset;
UINT32 StringsOffset;
UINT32 OffsetTop;
BOOLEAN Result;
UINT32 IndirectSymbolsOffset;
UINT32 LocalRelocationsOffset;
UINT32 ExternalRelocationsOffset;
MACH_NLIST_64 *SymbolTable;
MACH_NLIST_64 *IndirectSymtab;
MACH_RELOCATION_INFO *LocalRelocations;
@ -838,33 +855,43 @@ InternalInitialiseSymtabs64 (
FileSize = Context->FileSize;
Result = OcOverflowMulAddU32 (
Symtab->NumSymbols,
sizeof (MACH_NLIST_64),
Result = OcOverflowSubU32 (
Symtab->SymbolsOffset,
&OffsetTop
Context->ContainerOffset,
&SymbolsOffset
);
Result |= OcOverflowMulAddU32 (
Symtab->NumSymbols,
sizeof (MACH_NLIST_64),
SymbolsOffset,
&OffsetTop
);
if (Result || (OffsetTop > FileSize)) {
return FALSE;
}
Result = OcOverflowAddU32 (
Result = OcOverflowSubU32 (
Symtab->StringsOffset,
Symtab->StringsSize,
&OffsetTop
Context->ContainerOffset,
&StringsOffset
);
Result |= OcOverflowAddU32 (
StringsOffset,
Symtab->StringsSize,
&OffsetTop
);
if (Result || (OffsetTop > FileSize)) {
return FALSE;
}
MachoAddress = (UINTN)Context->MachHeader;
StringTable = (CHAR8 *)(MachoAddress + Symtab->StringsOffset);
StringTable = (CHAR8 *)(MachoAddress + StringsOffset);
if (Symtab->StringsSize == 0 || StringTable[Symtab->StringsSize - 1] != '\0') {
return FALSE;
}
Tmp = (VOID *)(MachoAddress + Symtab->SymbolsOffset);
Tmp = (VOID *)(MachoAddress + SymbolsOffset);
if (!OC_TYPE_ALIGNED (MACH_NLIST_64, Tmp)) {
return FALSE;
}
@ -902,49 +929,64 @@ InternalInitialiseSymtabs64 (
return FALSE;
}
Result = OcOverflowMulAddU32 (
DySymtab->NumIndirectSymbols,
sizeof (MACH_NLIST_64),
Result = OcOverflowSubU32 (
DySymtab->IndirectSymbolsOffset,
&OffsetTop
Context->ContainerOffset,
&IndirectSymbolsOffset
);
Result |= OcOverflowMulAddU32 (
DySymtab->NumIndirectSymbols,
sizeof (MACH_NLIST_64),
IndirectSymbolsOffset,
&OffsetTop
);
if (Result || (OffsetTop > FileSize)) {
return FALSE;
}
Result = OcOverflowMulAddU32 (
DySymtab->NumOfLocalRelocations,
sizeof (MACH_RELOCATION_INFO),
Result = OcOverflowSubU32 (
DySymtab->LocalRelocationsOffset,
&OffsetTop
Context->ContainerOffset,
&LocalRelocationsOffset
);
Result |= OcOverflowMulAddU32 (
DySymtab->NumOfLocalRelocations,
sizeof (MACH_RELOCATION_INFO),
LocalRelocationsOffset,
&OffsetTop
);
if (Result || (OffsetTop > FileSize)) {
return FALSE;
}
Result = OcOverflowMulAddU32 (
DySymtab->NumExternalRelocations,
sizeof (MACH_RELOCATION_INFO),
Result = OcOverflowSubU32 (
DySymtab->ExternalRelocationsOffset,
&OffsetTop
Context->ContainerOffset,
&ExternalRelocationsOffset
);
Result |= OcOverflowMulAddU32 (
DySymtab->NumExternalRelocations,
sizeof (MACH_RELOCATION_INFO),
ExternalRelocationsOffset,
&OffsetTop
);
if (Result || (OffsetTop > FileSize)) {
return FALSE;
}
Tmp = (VOID *)(MachoAddress + DySymtab->IndirectSymbolsOffset);
Tmp = (VOID *)(MachoAddress + IndirectSymbolsOffset);
if (!OC_TYPE_ALIGNED (MACH_NLIST_64, Tmp)) {
return FALSE;
}
IndirectSymtab = (MACH_NLIST_64 *)Tmp;
Tmp = (VOID *)(MachoAddress + DySymtab->LocalRelocationsOffset);
Tmp = (VOID *)(MachoAddress + LocalRelocationsOffset);
if (!OC_TYPE_ALIGNED (MACH_RELOCATION_INFO, Tmp)) {
return FALSE;
}
LocalRelocations = (MACH_RELOCATION_INFO *)Tmp;
Tmp = (VOID *)(MachoAddress + DySymtab->ExternalRelocationsOffset);
Tmp = (VOID *)(MachoAddress + ExternalRelocationsOffset);
if (!OC_TYPE_ALIGNED (MACH_RELOCATION_INFO, Tmp)) {
return FALSE;
}
@ -1176,7 +1218,7 @@ MachoGetFilePointerByAddress64 (
*MaxSize = (UINT32)(Segment->Size - Offset);
}
Offset += Segment->FileOffset;
Offset += Segment->FileOffset - Context->ContainerOffset;
return (VOID *)((UINTN)Context->MachHeader + (UINTN)Offset);
}
}
@ -1322,7 +1364,7 @@ MachoExpandImage64 (
//
// Do not overwrite header.
//
CopyFileOffset = Segment->FileOffset;
CopyFileOffset = Segment->FileOffset - Context->ContainerOffset;
CopyFileSize = Segment->FileSize;
CopyVmSize = Segment->Size;
if (CopyFileOffset <= HeaderSize) {
@ -1359,7 +1401,7 @@ MachoExpandImage64 (
DstSegment->FileOffset += CurrentDelta;
DstSegment->FileSize = DstSegment->Size;
if (DstSegment->VirtualAddress - DstSegment->FileOffset != FirstSegment->VirtualAddress) {
if (DstSegment->VirtualAddress - (DstSegment->FileOffset - Context->ContainerOffset) != FirstSegment->VirtualAddress) {
return 0;
}

View File

@ -662,7 +662,7 @@ MachoSymbolGetFileOffset64 (
return FALSE;
}
*FileOffset = (Section->Offset + (UINT32)Offset);
*FileOffset = (Section->Offset - Context->ContainerOffset + (UINT32)Offset);
if (MaxSize != NULL) {
*MaxSize = (UINT32)(Section->Size - Offset);

View File

@ -49,7 +49,7 @@ extern UINT32 VsmcKextInfoPlistDataSize;
static int FeedMacho(void *file, uint32_t size) {
OC_MACHO_CONTEXT Context;
if (!MachoInitializeContext (&Context, file, size)) {
if (!MachoInitializeContext (&Context, file, size, 0)) {
DEBUG ((DEBUG_WARN, "MachoInitializeContext failure\n"));
return -1;
}

View File

@ -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)) {
if (!MachoInitializeContext (&Context, file, size, 0)) {
return -1;
}