Nothing fails when an arm64 library loses its branch protection - #232
Merged
Merged
Conversation
Two regressions here are silent. A library built without -mbranch-protection still loads and still passes every test. An -march bump to armv8.3-a turns the PAC hints into retaa, which faults on an ARMv8.0 core. The check asserts both on every arm64 .so. No retaa or retab, and a feature note carrying BTI and PAC. It refuses an empty directory, because a build that produced no library would otherwise pass every assertion it makes. I ran it against real artifacts on both sides. The libraries built before #231 fail on libhttrack.so, whose note the unmarked OpenSSL statics cleared, and the ones built after it pass. A real build only ever produces the passing case, so the test drives the failures through stub tools. Two mutations of the checker each turn exactly one case red, which is what says the cases are not covering for each other. Signed-off-by: Xavier Roche <xroche@gmail.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The check asserts a BTI and PAC note on every arm64 library, which only holds once #231's OpenSSL carries one. Signed-off-by: Xavier Roche <xroche@gmail.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A failing llvm-objdump piped into grep -c reports zero matches, which the retaa check read as a pass. It now captures the disassembly first and exits when that fails. The note assertion alone passes a library that carries the note and signs no function, so the check also requires a paciasp. The test gains that case, plus one that pins the count in the pass line, because a walk that silently shrank would otherwise read as a clean run. Signed-off-by: Xavier Roche <xroche@gmail.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The paciasp assertion counted its mnemonic anywhere in the disassembly, and objdump prints the file path and every branch target. The same library passed or failed depending on the directory holding it, and a library exporting a function called paciasp passed while signing nothing. The match is now anchored to the instruction column. Two more ways through. llvm-readelf prints one feature line per note section, and bash globs span newlines, so a good line covered for a bad one. The check now wants exactly one. And find's status is lost through a process substitution, so a directory it could not read shrank the walk in silence. The stubs now copy the real tools, down to the path header and the lowercase "aarch64 feature". They printed what the script expected, which cannot catch the script expecting the wrong thing. Dropping the -i from that grep passed every case and turned every real library red. Six mutations, each killed by its own case. Retab dropped, the note match made case-sensitive, the instruction match unanchored. Then the disassembler no longer fail-closed, the two-note guard removed, and find's status ignored. The test moves into the native job, which is a required check, because the job it was in is not and it guards the gate. A failed check keeps the libraries now, since that is when they are worth reading. Signed-off-by: Xavier Roche <xroche@gmail.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two ways an arm64 library can lose its branch protection, both silent. A library built without
-mbranch-protectionstill loads and passes every test. An-marchbump to armv8.3-a turns the PAC hints intoretaa, which faults on an ARMv8.0 core.On every arm64
.sothe check wants noretaaorretab, onepaciaspin the instruction column, and one feature note naming BTI and PAC. It refuses an empty walk, a directory it could not read, and a failing tool, because each of those otherwise reads as a pass.I ran it against real libraries on both sides. The ones built before #231 fail on
libhttrack.so, whose note the unmarked OpenSSL statics cleared, and the ones built after it pass.A real build only produces the passing case, so the test drives the failures through stubs that copy the real tools' output, lowercase
aarch64 featureincluded. Six mutations of the checker each turn exactly one case red.The note assertion is right only now. Before #231 it was absent from a correctly built
libhttrack.so.