fix(modules): make bin-patch skip runnable binaries, prefer patchelf 🐛 - #325
fix(modules): make bin-patch skip runnable binaries, prefer patchelf 🐛#325dohernandez wants to merge 1 commit into
Conversation
Field trio from the pre-clarke launch: lief's full-file rewrite of the 291MB executor needs >18GB (std::bad_alloc on a 20GB box), cannot re-parse its own output (re-runs wedge), and emits corrupt section headers. Patching only ever sets interpreter/rpath, so: if the binary already executes on this machine there is nothing to patch (also makes re-runs idempotent); when patching is needed, use patchelf if available (in-place, valid output) and keep lief as a last resort with its import deferred and parse failures raised with a recovery hint. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
GenVM PR actionsTick a box to run it (the box unticks itself when handled). Actions only run while the PR has the
Full GenVM CI runs only when |
|
it was fixed in lief and manager builds newer version themselves now, but nixpkgs haven't accepted my patch yet NixOS/nixpkgs#538024 also this part was reworked I believe in manager |
Summary
Field report from the pre-clarke validator launch (2026-07-10): three distinct failures in post-install's
patch_executable(), all stemming from LIEF's full-file rewrite of the ~291MB executor just to set an RPATH:binary.write()needs a working set several times the binary size —std::bad_allocon a box with 18GB free.readelferrors out andpatchelfrefuses the file, so downstream tooling (stripping, signing, scanners) chokes.Fix
Patching only ever sets interpreter/rpath, so ask the ground-truth question first: when the target platform matches the host, exec
<binary> --version(60s timeout) before doing anything. Exit 0 means the loader resolved the interpreter and every needed library — skip patching entirely. This fixes all three issues for standard (FHS) deploys, where the shipped tree's interpreter resolves and$ORIGIN/../libRUNPATH already works, and makes re-runs idempotent: a binary patched by a previous run executes and is skipped, so LIEF never re-parses its own output. (A static "is$ORIGIN/../libpresent" check — the field report's suggestion — would not have sufficed: the code sets two rpath dirs and$ORIGIN/../libcovers only one, so dir-coverage would still "need" patching on every FHS box.)When patching is genuinely needed (e.g. NixOS-style hosts where the interpreter doesn't resolve):
patchelfwhen the file is ELF and the CLI is on PATH:--print-interpreter,--set-interpreteronly if the current one doesn't resolve (same rule as before), and--force-rpath --set-rpath(DT_RPATH, parity with what the LIEF path writes). In-place edit — no memory multiplier, output stays valid for section-parsing tools.libstdc++.so.6venv quirk), and a parse failure now raises with a recovery hint instead of the previous silentreturnthat shipped a possibly-unpatched binary.Verification
E2E against the real script on three fake bundle trees:
bin/genvm-modulesandexecutor/<v>/bin/genvmskipped, exit 0, and LIEF provably never imported (the test python has no lief installed);patchelfstub on PATH → argv exactly--print-interpreterthen--force-rpath --set-rpath <root>/lib[:<exec>/lib]per binary, no--set-interpreter(stub interpreter resolves), no LIEF.Known limit: the patchelf path was validated against a stub (no linux-ELF + patchelf pair on this dev machine); a real NixOS smoke-run of
setup.pyis being arranged via the dev-env team once this lands in an rc.Merges cleanly on top of #323 — different regions of the same file; both add
import shutil. In the step flow, #323's platform check runs before this precheck, so a wrong-platform binary is deleted/re-downloaded before anything asks whether it "runs".🤖 Generated with Claude Code