Skip to content

fix(build): make post-install ELF interpreter patching relocatable - #5

Open
dohernandez wants to merge 1 commit into
v0.6-devfrom
fix/reloc-safe-interpreter
Open

fix(build): make post-install ELF interpreter patching relocatable#5
dohernandez wants to merge 1 commit into
v0.6-devfrom
fix/reloc-safe-interpreter

Conversation

@dohernandez

Copy link
Copy Markdown
Member

The bug (reported via NOD-1026, node rollout of v0.6.1)

post-install.py's lief bin-patch rewrites each binary's ELF program interpreter (PT_INTERP) to an absolute in-tree path<install-dir>/lib/libc.so — computed at whatever directory post-install runs in. If the tree is moved after post-install, that path is stale and the kernel fails to exec the binary:

fork/exec .../bin/genvm-modules: no such file or directory   # file exists — it's the loader that's missing

Hit on 2 boxes during rollout; only manual tarball installs that stage-then-move are affected (automated deploys run post-install in place). Verified on genvm v0.6.0-rc0.

Fix (self-contained, post-install only)

  1. Idempotent re-point. patch_executable skipped patching whenever the current interpreter path merely existed. It now re-points whenever the interpreter isn't already the wanted absolute path. So re-running post-install in the final location always corrects a stale PT_INTERP — even if the old path still lingers (copied, not moved).
  2. --install-root override. A staged installer that builds in dir A but deploys to dir B can now run post-install.py --install-root /final/path to bake B's loader in one pass, no re-run needed. Validated to be absolute (PT_INTERP requires it).

Scope / what this does NOT do

PT_INTERP must be absolute — the kernel does not honor $ORIGIN/relative interpreters — so a binary cannot be made freely relocatable after install by this change alone. Full "move the installed tree anywhere, anytime, no action" would require a launcher that re-execs via the loader plus changing how genvm resolves its own dir (it uses std::env::current_exe()/proc/self/exe, which a loader-launcher would break), and the executor binary lives in the genvm-executor submodule — i.e. a cross-repo change. That's out of scope here; this PR makes the in-place / staged-install path robust, which covers the reported failure.

Testing

  • py_compile clean; --help shows --install-root; relative --install-root is rejected.
  • ⚠️ The lief ELF re-patch itself isn't exercised locally (needs a Linux ELF + the bundled musl loader). Behavior is unchanged except the skip condition; validated by CI / a real bundle.

Node side: NOD-1026 (https://linear.app/genlayer-labs/issue/NOD-1026) tracks the node's doctor/self-heal mitigation.

🤖 Generated with Claude Code

post-install baked an absolute in-tree PT_INTERP at the directory it ran
in, so moving the tree afterwards left a stale interpreter and the
binaries failed to exec (kernel reports ENOENT for the loader, which
misleadingly implicates the executable itself). Manual tarball installs
that stage then move hit this; automated deploys that run post-install
in place do not.

Two self-contained fixes in post-install:
- Re-point the interpreter whenever it differs from the wanted absolute
  path, instead of only when the current one is missing. This makes the
  patch idempotent and lets a re-run in the final location always
  correct a stale PT_INTERP, even if the old path still exists.
- Add --install-root so a staged install can bake the FINAL location's
  lib/libc.so into PT_INTERP in one pass (PT_INTERP must be absolute, so
  it cannot be made relative; targeting the final path is the fix).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 74958e21-dab0-4931-9f69-612a46717235

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/reloc-safe-interpreter

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

GenVM PR actions

Tick a box to run it (the box unticks itself when handled). Actions only run while the PR has the ci-safe label.

  • Force run full tests
  • Rerun full tests
  • Merge into dev

Full GenVM CI runs only when rtm or run-full-tests is set — "Force run full tests" is a sticky toggle for run-full-tests. Adding rtm marks the PR ready-to-merge and also runs full tests. Merge requires: rtm, green full tests, green E2E, and the branch 0 commits behind.

@dohernandez
dohernandez requested a review from kp2pml30 July 16, 2026 14:24
@github-actions github-actions Bot added the not rebased branch is behind its base; rebase before it can be merged label Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-safe not rebased branch is behind its base; rebase before it can be merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant