From bbaeb1ee0ee03ffd5161f1414c8b36d7d7fcdbb7 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Fri, 25 Feb 2022 11:43:44 -0800 Subject: Validate chained fixup image formats This is part of a series of patches to upstream support for Mach-O chained fixups. Differential Revision: https://reviews.llvm.org/D113725 --- llvm/lib/Object/MachOObjectFile.cpp | 54 ++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 13 deletions(-) (limited to 'llvm/lib/Object/MachOObjectFile.cpp') diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp index 5d6e237..a3e0516 100644 --- a/llvm/lib/Object/MachOObjectFile.cpp +++ b/llvm/lib/Object/MachOObjectFile.cpp @@ -3259,13 +3259,13 @@ MachOChainedFixupEntry::MachOChainedFixupEntry(Error *E, bool Parse) : MachOAbstractFixupEntry(E, O) { ErrorAsOutParameter e(E); - if (Parse) { - if (auto FixupTargetsOrErr = O->getDyldChainedFixupTargets()) - FixupTargets = *FixupTargetsOrErr; - else { - *E = FixupTargetsOrErr.takeError(); - return; - } + if (!Parse) + return; + if (auto FixupTargetsOrErr = O->getDyldChainedFixupTargets()) + FixupTargets = *FixupTargetsOrErr; + else { + *E = FixupTargetsOrErr.takeError(); + return; } } @@ -4763,11 +4763,11 @@ ArrayRef MachOObjectFile::getDyldInfoLazyBindOpcodes() const { return makeArrayRef(Ptr, DyldInfo.lazy_bind_size); } -Expected> -MachOObjectFile::getDyldChainedFixupTargets() const { +Expected> +MachOObjectFile::getChainedFixupsHeader() const { // Load the dyld chained fixups load command. if (!DyldChainedFixupsLoadCmd) - return std::vector(); + return llvm::None; auto DyldChainedFixupsOrErr = getStructOrErr( *this, DyldChainedFixupsLoadCmd); if (!DyldChainedFixupsOrErr) @@ -4775,11 +4775,10 @@ MachOObjectFile::getDyldChainedFixupTargets() const { MachO::linkedit_data_command DyldChainedFixups = DyldChainedFixupsOrErr.get(); // If the load command is present but the data offset has been zeroed out, - // as is the case for dylib stubs, return an empty list of targets. + // as is the case for dylib stubs, return None (no error). uint64_t CFHeaderOffset = DyldChainedFixups.dataoff; - std::vector Targets; if (CFHeaderOffset == 0) - return Targets; + return DyldChainedFixupsOrErr.takeError(); // Load the dyld chained fixups header. const char *CFHeaderPtr = getPtr(*this, CFHeaderOffset); @@ -4798,6 +4797,35 @@ MachOObjectFile::getDyldChainedFixupTargets() const { Twine("bad chained fixups: unknown imports format: ") + Twine(CFHeader.imports_format)); + // Validate the image format. + // + // Load the image starts. + uint64_t CFImageStartsOffset = (CFHeaderOffset + CFHeader.starts_offset); + if (CFHeader.starts_offset < sizeof(MachO::dyld_chained_fixups_header)) { + return malformedError(Twine("bad chained fixups: image starts offset ") + + Twine(CFHeader.starts_offset) + + " overlaps with chained fixups header"); + } + uint32_t EndOffset = DyldChainedFixups.dataoff + DyldChainedFixups.datasize; + if (CFImageStartsOffset + sizeof(MachO::dyld_chained_starts_in_image) > + EndOffset) { + return malformedError(Twine("bad chained fixups: image starts end ") + + Twine(CFImageStartsOffset + + sizeof(MachO::dyld_chained_starts_in_image)) + + " extends past end " + Twine(EndOffset)); + } + + return CFHeader; +} + +Expected> +MachOObjectFile::getDyldChainedFixupTargets() const { + auto CFHeaderOrErr = getChainedFixupsHeader(); + if (!CFHeaderOrErr) + return CFHeaderOrErr.takeError(); + std::vector Targets; + if (!(*CFHeaderOrErr)) + return Targets; return Targets; } -- cgit v1.1