<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/117723>117723</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Artificial MachO binary processed by llvm-objcopy/strip is not accepted by codesign
</td>
</tr>
<tr>
<th>Labels</th>
<td>
bug,
tools:llvm-objcopy/strip,
platform:macos
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
RIscRIpt
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
RIscRIpt
</td>
</tr>
</table>
<pre>
## 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](https://github.com/darlinghq/darling-security/blob/9bba1c54a75a30ba826e2ff07f17e64c5c0fdf98/OSX/libsecurity_utilities/lib/macho%2B%2B.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.
- [1] https://github.com/llvm/llvm-project/blob/ec41462d7a7d2fcd74dcf1c60218f134fcfd55b2/llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.cpp#L364-L368
- [2] https://github.com/llvm/llvm-project/blob/ec41462d7a7d2fcd74dcf1c60218f134fcfd55b2/llvm/lib/ObjCopy/MachO/MachOWriter.cpp#L92-L94
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzMVk2P2zYQ_TX0ZWBDor7sgw-2NwYW2DZFNkV7KyhyZHFDkQo5cur8-oKSnHWQbZAUCVDAgG1p-Phm-DhvRAj6ZBG3rNgzzt_cB_nmvifGOSvuFmKg1vnt9emiduqyZTxjPIPHS9eT61iyY8lu50k3Wmph4Bch29dQayv8BXrvJIaACuoLGHPulq5-kq6_MH4M5HUPOoB1BEJK7GmKk05hZLWasK9_oRHaBPigqQX03nmW7aYIlr2CTmgL-DfKgURtcAxGBXETSXAWRitB2tl5xZTDvT1jIH26vtlJ6bzS9gTkgBX7O-GNtifGj0bXAeXgNV3-GkgbTRrD9JzxYydk6xjfM75fyb5nxR3j65aoD5EjPzJ-PGlqh3olXcf4UU247fvn38srPOPH2riIuqlrkcoiF1UhsqQWa14ib5qkatIKy1wWMmlUs1kzfnz9-Oe3kiwizWImyjdzPcpk_iS770u1OvBsDdIZyFh1gO5xCL2W2g0BWHYH5Adk2f4_wJZpNcJWPxiWb34KbFaMsOsfDJtnI2z5g2GLfIQtvg57q4ovbkeZjDc9CjzbzfcLH8kPkgaPnxalK3jbIoShA9cAtQhGBIrLH5xQB9d1wipWJiCsAk0Bgv6I0A2BAN8PwsS94ipyJMz00jXAOG9E7FIgXdc7i5YYP7Bk96HVsoXgOiTdYQDpvMfQO6vCFQmtihCNNrh6ObHfrT6jD8JMyT3_vUlqZ_TJdmjpX-iEKYcawWAIQK2wwFnxKksYP8RkWbLjU21Oop8Sq5E-INpvhYvVElcaMZXsGe8a3WgT2-DYND-id1BfCEMMzlfwq4Onwb6D0ApjYnQfj-amPuD8S2RWt0009tE3aPAsLIHH94P2GAlNMUfvurHqonZnjL88QmjdYFTc0DpQggRoO_vGyEA6S2POrgEBxgkV945CmRKZVORPOAnJNU1AYnwfi8jK5DN68Jt3tcEOFAbpdX_jAWXymSOVCSiHkx0NfVRzBNdWaY-SwqVzTRODGo1GgZ7E7DEMhqJ0WJncz7GPl-5tNKEYzfhaNIR-dKK-H91kE10Pu54u0WRSVtytYBdAzGgvb_sOsQ_gjIpmNmBU0SR2HeAkfC1OOCsLpLDQO21pKucLJfrsLt4W-Asi4717jKv4OtpFmYBHGrydbyq1giKF8Tz8JMzxvCXF2ztljWo-Xlbs42Axn9DbVgeQBoU3FzhrZwRhAGfxSk-2KN8FiHLSzqKaVcT4ehKS8Diqejmq-ir27096orO8ngZ8xbqjZOavZe_dE0p6dmyUeZqXXFWiUryRqsqVbFJZJjxdN2mWN7JRRVHzG5yxQ7-unw7TUDT11Pn7QVzcQPtBG4V-8uvsISvz5UNWrq-E-f-I8B9e0zPTDV8-bPKF2mZqk23EArdplfEyy_O0XLTbsuEya0opyk3DyzorN5gVVZlWKk-xxmqhtzzheZryMi14kiartEJV5zWqLF2vueAsT7AT2qwit5Xzp4UOYcBtmlYVzxZG1GjCPNnWwykOtfzAOCfnTKzWSwPpp6DeCGqc71i264R0YR6J_XZcVQ-nwPLE6EDheXvSZHD7U4bhxeDN9ruPeaxHnATmkpy3_J8AAAD__ya66Bs">