Skip to content

Commit

Permalink
Revert "Extract LC_CODE_SIGNATURE related implementation out of LLD"
Browse files Browse the repository at this point in the history
This reverts commit cc82296.

As discussed in the review of https://reviews.llvm.org/D109972, this was not
right approach, so we are reverting to start with a different approach.

Differential Revision: https://reviews.llvm.org/D110974
  • Loading branch information
drodriguez committed Oct 2, 2021
1 parent 91dfc08 commit 657f02d
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 198 deletions.
96 changes: 84 additions & 12 deletions lld/MachO/SyntheticSections.cpp
Expand Up @@ -24,6 +24,11 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SHA256.h"

#if defined(__APPLE__)
#include <sys/mman.h>
#endif

#ifdef LLVM_HAVE_LIBXAR
#include <fcntl.h>
Expand Down Expand Up @@ -1146,30 +1151,97 @@ void StringTableSection::writeTo(uint8_t *buf) const {
}
}

static_assert((CodeSignatureSection::blobHeadersSize % 8) == 0, "");
static_assert((CodeSignatureSection::fixedHeadersSize % 8) == 0, "");

CodeSignatureSection::CodeSignatureSection()
: LinkEditSection(segment_names::linkEdit, section_names::codeSignature) {
align = object::CodeSignatureSection::Align; // required by libstuff
align = 16; // required by libstuff
// FIXME: Consider using finalOutput instead of outputFile.
fileName = config->outputFile;
size_t slashIndex = fileName.rfind("/");
if (slashIndex != std::string::npos)
fileName = fileName.drop_front(slashIndex + 1);
allHeadersSize = alignTo<16>(fixedHeadersSize + fileName.size() + 1);
fileNamePad = allHeadersSize - fixedHeadersSize - fileName.size();
}

uint32_t CodeSignatureSection::getBlockCount() const {
return (fileOff + blockSize - 1) / blockSize;
}

uint64_t CodeSignatureSection::getRawSize() const {
return static_cast<uint64_t>(sectionBuilder->getRawSize());
return allHeadersSize + getBlockCount() * hashSize;
}

void CodeSignatureSection::writeHashes(uint8_t *buf) const {
sectionBuilder->write(buf);
uint8_t *code = buf;
uint8_t *codeEnd = buf + fileOff;
uint8_t *hashes = codeEnd + allHeadersSize;
while (code < codeEnd) {
StringRef block(reinterpret_cast<char *>(code),
std::min(codeEnd - code, static_cast<ssize_t>(blockSize)));
SHA256 hasher;
hasher.update(block);
StringRef hash = hasher.final();
assert(hash.size() == hashSize);
memcpy(hashes, hash.data(), hashSize);
code += blockSize;
hashes += hashSize;
}
#if defined(__APPLE__)
// This is macOS-specific work-around and makes no sense for any
// other host OS. See https://openradar.appspot.com/FB8914231
//
// The macOS kernel maintains a signature-verification cache to
// quickly validate applications at time of execve(2). The trouble
// is that for the kernel creates the cache entry at the time of the
// mmap(2) call, before we have a chance to write either the code to
// sign or the signature header+hashes. The fix is to invalidate
// all cached data associated with the output file, thus discarding
// the bogus prematurely-cached signature.
msync(buf, fileOff + getSize(), MS_INVALIDATE);
#endif
}

void CodeSignatureSection::writeTo(uint8_t *buf) const {
// The entire code section including header is written
// in CodeSignatureSection::writeHashes above.
}

void CodeSignatureSection::finalize() {
uint32_t signatureSize = static_cast<uint32_t>(getSize());
auto *superBlob = reinterpret_cast<CS_SuperBlob *>(buf);
write32be(&superBlob->magic, CSMAGIC_EMBEDDED_SIGNATURE);
write32be(&superBlob->length, signatureSize);
write32be(&superBlob->count, 1);
auto *blobIndex = reinterpret_cast<CS_BlobIndex *>(&superBlob[1]);
write32be(&blobIndex->type, CSSLOT_CODEDIRECTORY);
write32be(&blobIndex->offset, blobHeadersSize);
auto *codeDirectory =
reinterpret_cast<CS_CodeDirectory *>(buf + blobHeadersSize);
write32be(&codeDirectory->magic, CSMAGIC_CODEDIRECTORY);
write32be(&codeDirectory->length, signatureSize - blobHeadersSize);
write32be(&codeDirectory->version, CS_SUPPORTSEXECSEG);
write32be(&codeDirectory->flags, CS_ADHOC | CS_LINKER_SIGNED);
write32be(&codeDirectory->hashOffset,
sizeof(CS_CodeDirectory) + fileName.size() + fileNamePad);
write32be(&codeDirectory->identOffset, sizeof(CS_CodeDirectory));
codeDirectory->nSpecialSlots = 0;
write32be(&codeDirectory->nCodeSlots, getBlockCount());
write32be(&codeDirectory->codeLimit, fileOff);
codeDirectory->hashSize = static_cast<uint8_t>(hashSize);
codeDirectory->hashType = kSecCodeSignatureHashSHA256;
codeDirectory->platform = 0;
codeDirectory->pageSize = blockSizeShift;
codeDirectory->spare2 = 0;
codeDirectory->scatterOffset = 0;
codeDirectory->teamOffset = 0;
codeDirectory->spare3 = 0;
codeDirectory->codeLimit64 = 0;
OutputSegment *textSeg = getOrCreateOutputSegment(segment_names::text);
// NOTE: ld64 seems to also use outputFile instead of finalOutput
sectionBuilder = std::make_unique<object::CodeSignatureSection>(
fileOff, config->outputFile, config->outputType, textSeg->fileOff,
textSeg->fileSize);
write64be(&codeDirectory->execSegBase, textSeg->fileOff);
write64be(&codeDirectory->execSegLimit, textSeg->fileSize);
write64be(&codeDirectory->execSegFlags,
config->outputType == MH_EXECUTE ? CS_EXECSEG_MAIN_BINARY : 0);
auto *id = reinterpret_cast<char *>(&codeDirectory[1]);
memcpy(id, fileName.begin(), fileName.size());
memset(id + fileName.size(), 0, fileNamePad);
}

BitcodeBundleSection::BitcodeBundleSection()
Expand Down
18 changes: 13 additions & 5 deletions lld/MachO/SyntheticSections.h
Expand Up @@ -21,7 +21,6 @@
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Object/MachO.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"

Expand Down Expand Up @@ -477,15 +476,24 @@ class IndirectSymtabSection final : public LinkEditSection {
// The code signature comes at the very end of the linked output file.
class CodeSignatureSection final : public LinkEditSection {
public:
static constexpr uint8_t blockSizeShift = 12;
static constexpr size_t blockSize = (1 << blockSizeShift); // 4 KiB
static constexpr size_t hashSize = 256 / 8;
static constexpr size_t blobHeadersSize = llvm::alignTo<8>(
sizeof(llvm::MachO::CS_SuperBlob) + sizeof(llvm::MachO::CS_BlobIndex));
static constexpr uint32_t fixedHeadersSize =
blobHeadersSize + sizeof(llvm::MachO::CS_CodeDirectory);

uint32_t fileNamePad = 0;
uint32_t allHeadersSize = 0;
StringRef fileName;

CodeSignatureSection();
uint64_t getRawSize() const override;
bool isNeeded() const override { return true; }
void writeTo(uint8_t *buf) const override;
uint32_t getBlockCount() const;
void writeHashes(uint8_t *buf) const;
void finalize() override;

private:
std::unique_ptr<llvm::object::CodeSignatureSection> sectionBuilder;
};

class BitcodeBundleSection final : public SyntheticSection {
Expand Down
38 changes: 0 additions & 38 deletions llvm/include/llvm/Object/MachO.h
Expand Up @@ -733,44 +733,6 @@ inline const ObjectFile *DiceRef::getObjectFile() const {
return OwningObject;
}

class CodeSignatureSection {
public:
uint32_t getRawSize() const;
uint32_t getSize() const;

static constexpr int Align = 16;
static constexpr uint8_t BlockSizeShift = 12;
static constexpr size_t BlockSize = (1 << BlockSizeShift); // 4 KiB
static constexpr size_t HashSize = 256 / 8;
static constexpr size_t BlobHeadersSize =
alignTo<8>(sizeof(MachO::CS_SuperBlob) + sizeof(MachO::CS_BlobIndex));
static constexpr uint32_t FixedHeadersSize =
BlobHeadersSize + sizeof(MachO::CS_CodeDirectory);

CodeSignatureSection(uint64_t FileOff, StringRef OutputFilePath,
MachO::HeaderFileType OutputFileType,
uint64_t TextSegmentFileOff,
uint64_t TextSegmentFileSize);

void write(uint8_t *Buf) const;

private:
uint32_t getAllHeadersSize() const;
uint32_t getBlockCount() const;
uint32_t getFileNamePad() const;

StringRef stripOutputFilePath(const StringRef OutputFilePath);

// FileOff is the offset relative to the start of the file
// used to access the start of code signature section
// in __LINKEDIT segment
uint64_t FileOff;
StringRef OutputFileName;
MachO::HeaderFileType OutputFileType;
uint64_t TextSegmentFileOff;
uint64_t TextSegmentFileSize;
};

} // end namespace object
} // end namespace llvm

Expand Down
1 change: 0 additions & 1 deletion llvm/lib/Object/CMakeLists.txt
Expand Up @@ -2,7 +2,6 @@ add_llvm_component_library(LLVMObject
Archive.cpp
ArchiveWriter.cpp
Binary.cpp
CodeSignatureSection.cpp
COFFImportFile.cpp
COFFModuleDefinition.cpp
COFFObjectFile.cpp
Expand Down
142 changes: 0 additions & 142 deletions llvm/lib/Object/CodeSignatureSection.cpp

This file was deleted.

0 comments on commit 657f02d

Please sign in to comment.