Skip to content

Artificial MachO binary processed by llvm-objcopy/strip is not accepted by codesign #117723

@RIscRIpt

Description

@RIscRIpt

Symptom

Artificial MachO binary processed by llvm-objcopy/strip is not accepted by codesign.

codesign fails with error:

main executable failed strict validation

Investigation

According to Darling/libsecurity_utilities/lib/macho++.cpp

libsecurity_utilities/lib/macho++.cpp|238 col 3| mSuspicious = true;
libsecurity_utilities/lib/macho++.cpp|617 col 7| mSuspicious = true;
libsecurity_utilities/lib/macho++.cpp|629 col 7| mSuspicious = true;
libsecurity_utilities/lib/macho++.cpp|635 col 8| mSuspicious = true;
libsecurity_utilities/lib/macho++.cpp|643 col 6| mSuspicious = true;
libsecurity_utilities/lib/macho++.cpp|654 col 5| mSuspicious = true;

According to MachO::validateStructure

  1. The sum of the last LoadCommand and its size must equal to the total size of "fat" component,
    which sometimes corresponds to the end of file.

According to Universal::Universal

  1. Alignment of "fat" components must be less than 2^30, and
  2. The gap size between "fat" components must be less than its alignment.
  3. The gap must be filled with zero bytes.
  4. No junk shall be past end of file or "fat" component.

Relevant requirement

From the above there should be no data in MachO past contents of a load command with the largest offset+size.

Problem description

llvm-objcopy does not update indirectsymoff field if the resulting IndirectSymTable (after stripping) is empty [1]. As a result indirectsymoff keeps old value, which is garbage, and can point past offset+size of the last load command. As a result totalSize() returns size that is larger than the actual stripped MachO [2].

This clearly violates one of the checks mentioned above (there are zero-bytes filled past offset+size of the last load command.

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions