Skip to content

Restore Android ELF runpath#1

Closed
GFernie wants to merge 3 commits intoDioNanos:mainfrom
GFernie:fix/android-elf-runpath
Closed

Restore Android ELF runpath#1
GFernie wants to merge 3 commits intoDioNanos:mainfrom
GFernie:fix/android-elf-runpath

Conversation

@GFernie
Copy link
Copy Markdown

@GFernie GFernie commented Mar 25, 2026

Summary

Restore an Android runpath on the native Codex ELF so codex.bin can resolve its bundled libc++_shared.so even when it is launched directly without the Node wrapper environment.

Bug report: GFernie#1

Problem

On Termux, the latest package can fail when apply_patch or another direct native-binary launch path bypasses the wrapper-provided LD_LIBRARY_PATH.

Observed interactive apply_patch failure:

• Added thread_apply_patch_probe.txt (+1 -0)
    1 +probe

✘ Failed to apply patch
  └ CANNOT LINK EXECUTABLE "/data/data/com.termux/files/usr/lib/node_modules/@mmmbuto/codex-cli-termux/bin/codex.bin": library "libc++_shared.so" not found: needed by main executable

The same failure is also reproducible by launching the packaged ELF directly in a stripped environment.

Change

This PR keeps the runtime fix minimal:

  • add -Wl,-rpath,$ORIGIN next to the existing Android -lc++_shared linker flag in codex-rs/.cargo/config.toml
  • strengthen verify-patches.sh so Patch "OpenAI rejected the request" openai/codex#10 performs runtime ELF verification when a built binary pair is available
  • document that stronger verification in the patch inventory

With that change, the rebuilt Android binary carries a runpath containing $ORIGIN, so the loader can find the sibling shared runtime without depending on wrapper-set environment variables.

Validation

  • bash verify-patches.sh
  • readelf -d confirms the older known-good packaged binaries expose RUNPATH [$ORIGIN] on both codex.bin and codex-exec.bin
  • readelf -d confirms the newer broken packaged binaries do not expose that runpath, which is the regression pattern this check is meant to catch

verify-patches.sh now behaves in two modes:

  • source-only checkout: verifies the launcher/package wiring and reports that runtime proof was skipped because no ELF pair was found
  • built/package checkout: additionally requires RUNPATH or RPATH containing $ORIGIN on both binaries

Scope

This PR is intentionally limited to the Android linker regression. A separate Termux issue around persistent approval rule storage (lock() not supported) is not part of this change (GFernie#3).

GFernie and others added 2 commits March 25, 2026 16:27
Add `-Wl,-rpath,$ORIGIN` to the Android Rust linker flags so the bundled binaries can resolve `libc++_shared.so` when they are launched directly without a wrapper-provided `LD_LIBRARY_PATH`. This fixes the Termux linker failure while leaving approval and tool behaviour unchanged.

Verified by rebuilding `codex-cli` and running `codex --version` under an empty environment.

Co-authored-by: Codex <codex@openai.com>
Update the patch inventory and verification script so the Termux fork records the restored Android RUNPATH behaviour alongside the existing launcher hardening notes. This keeps the compatibility delta documented in the repo's patch workflow.

Verified with verify-patches.sh.

Co-authored-by: Codex <codex@openai.com>
Copy link
Copy Markdown
Owner

DioNanos commented Apr 3, 2026

Thanks, this looks like a sensible hardening step.

Adding -Wl,-rpath,$ORIGIN on Android seems like a good complement to the existing wrapper-based fix, especially for cases where the native ELF gets invoked more directly and the wrapper-provided LD_LIBRARY_PATH is not preserved.

One thing that may be worth tightening before we roll it into a release: the current verification only checks that the linker flag is present in source config. Since the bug shows up at runtime in the produced ELF, it would be even better if the verification also checked the built/package binary itself, for example with readelf -d to confirm a RUNPATH/RPATH containing $ORIGIN, and ideally on both codex.bin and codex-exec.bin.

That would make the fix much easier to trust long-term across rebases and toolchain changes.

From my side the direction looks good; I’d just like to integrate the runtime proof as well so the next release carries both the fix and a stronger guard against regressions.

DioNanos pushed a commit that referenced this pull request Apr 3, 2026
Integrate PR #1 from GFernie into the latest Termux release prep.

Add Android RUNPATH=$ORIGIN linker hardening, teach verify-patches.sh to validate the packaged ELFs at the binary level, and align maintainer/user docs with the layered libc++_shared.so fix path.

Co-authored-by: GFernie <9322279+GFernie@users.noreply.github.com>
Update Patch openai#10 verification so it can inspect real ELF outputs instead of only source wiring. When a built binary pair is available, verify-patches.sh now uses readelf to require RUNPATH or RPATH containing $ORIGIN on both codex and codex-exec.

The script still passes in source-only checkouts by skipping runtime proof when no ELF pair is present, and it ignores the shell launcher scripts in npm-package/bin. patches/README.md now documents the stronger runtime check.

Co-authored-by: Codex <codex@openai.com>
@GFernie GFernie marked this pull request as draft April 3, 2026 22:06
@GFernie
Copy link
Copy Markdown
Author

GFernie commented Apr 4, 2026

Effectively merged via 91a8611

@GFernie GFernie closed this Apr 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants