[GH-ISSUE #5717] [Bug] inspect-binary-layout rejects a valid relocatable object referencing linux_banner #3468

Closed
opened 2026-10-31 00:40:48 +00:00 by bsakaguchi · 2 comments
Owner

Originally created by @coygeek on GitHub (Oct 20, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/5717

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Native analysis or decompilation

Observed behavior

inspect-binary-layout returns execution_failure and no layout Evidence for a compiler-generated ELF64 x86-64 relocatable object referencing the undefined symbol linux_banner. An otherwise equivalent object referencing ordinary_banner succeeds. An independent verifier executed each CLI case once at the baseline below; this submission retains that attribution rather than claiming another runtime replay.

Reproduction

From the built source checkout on Linux x64, with REA_PWNTOOLS_PYTHON set to the absolute executable of the caller-supplied pinned Python environment:

work_dir="$(mktemp -d)"
pwn_python="$REA_PWNTOOLS_PYTHON"
mkdir -p "$work_dir/home" "$work_dir/cfg" "$work_dir/data" \
  "$work_dir/cache" "$work_dir/state" "$work_dir/temp"
cat > "$work_dir/module.c" <<'C'
extern const char linux_banner[];
const char *module_banner(void) { return linux_banner; }
C
sed 's/linux_banner/ordinary_banner/g' "$work_dir/module.c" > "$work_dir/control.c"
gcc -O1 -c "$work_dir/module.c" -o "$work_dir/module.o"
gcc -O1 -c "$work_dir/control.c" -o "$work_dir/control.o"
inspect_object() {
  env -i PATH="$PATH" HOME="$work_dir/home" XDG_CONFIG_HOME="$work_dir/cfg" \
    XDG_DATA_HOME="$work_dir/data" XDG_CACHE_HOME="$work_dir/cache" \
    XDG_STATE_HOME="$work_dir/state" TMPDIR="$work_dir/temp" \
    REA_LOG_LEVEL=silent REA_PWNTOOLS_PYTHON="$pwn_python" \
    node scripts/rea.mjs inspect-binary-layout "$1" --json
}
for object in module control; do
  readelf -aW "$work_dir/$object.o"
  objdump -h -x "$work_dir/$object.o"
  nm "$work_dir/$object.o"
  inspect_object "$work_dir/$object.o" > "$work_dir/$object.json"
  printf '%s exit: %s\n' "$object" "$?"
done
cat "$work_dir/module.json"

The verifier ran equivalent commands with isolated HOME/XDG/TMPDIR directories and env -i. All three binutils readers exited 0 for both objects; REA exited 1 for module.o and 0 for the control. The fixtures were inspected without executing them.

Expected behavior

Return layout Evidence for this supported object, retaining the original sections, symbol-table identities and section-relative relocations. linux_banner must remain undefined with value zero. Its spelling does not make the relocatable object a mapped kernel image.

Contract: docs/binary-diagnostics.md supports Linux x64 ELF64 x86-64 little-endian EXEC/DYN/REL, undefined symbol values and section-relative relocations; src/contracts/native/binaryDiagnosticsToolContracts.ts:50 exposes the offline layout operation.

Impact and scope

P2: a bounded compatibility defect prevents the entire supported offline layout inspection for this symbol reference. The ordinary-symbol control succeeds, returning 12 sections, 5 symbols and 2 relocations. Broader kernel-module coverage, other architectures and MCP were not tested. Independent binutils inspection works but does not return REA Evidence; no REA workaround preserving this artifact was verified. Renaming the symbol changes the analyzed bytes.

REA version

rea-agents 6.7.0, source baseline 9d8e7803326a382cbbb3ffdb900f5e93e5442d68. Verified at baseline; main source-checked only at 84c89d1107cda017509bc3cd851573d073f9906d. No intervening commits change the cited docs, contract, bridge files or TypeScript decoder; the package lock is unchanged. No fresh main runtime replay was performed.

Runtime and platform

Observed reproduction: Linux amd64 container, Node.js v24.22.0; gcc 12.2.0; caller-supplied pwntools 4.15.0, pyelftools 0.33 and Unicorn 2.1.2. Submission host, not the reproduction platform: Node.js v26.12.0; macOS 27.0.1; arm64. Hopper/Ghidra are not involved.

Target and artifact context

Self-built ELF64 little-endian x86-64 ET_REL object with no program headers. Its symbol-table entry 4 is GLOBAL/UND linux_banner, value zero; a PC-relative relocation references it. The control changes only the symbol spelling in the C source before recompilation.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

Observed failing CLI subset (private snapshot operand omitted):

{
  "code": "execution_failure",
  "retryable": false,
  "details": {
    "provider_id": "pwntools-elf",
    "operation": "inspect_binary_layout",
    "diagnostics": {
      "phase": "decoder",
      "failure_kind": "decoder"
    }
  }
}

The diagnostic reason begins PwnlibException: Address 0x3 is not contained in LayoutELF; the top-level message recommends rea doctor. Direct unchanged pwntools ELF(path, checksec=False) also fails for the same object, with _populate_kernel_version → string → read in its traceback, and succeeds for the control.

In a separate scratch-only diagnostic process, disabling only the upstream kernel-version probe allows parsing to finish: its convenience symbol map has linux_banner: 3 and got.linux_banner: 3, while the original symbol table still has SHN_UNDEF and st_value: 0. This is causal evidence, not a fix or successful public CLI restoration.

Typed outcome or recovery expected

Exit 0 with layout Evidence for the same artifact digest, preserving linux_banner as SHN_UNDEF, value zero, undefined value meaning and its original table/entry indices, plus the original relocation identities. Preserve control success. Translating the exception to an invalid-format refusal or suppressing the symbol would still reject or misrepresent supported input.

Analysis or suspected cause

Source-derived explanation supported by the direct traceback: the exception originates in upstream Gallopsled/pwntools 4.15.0, in the caller-supplied pinned dependency environment. Pwntools skips undefined entries in its normal symbol map, creates a synthetic GOT convenience entry at relocation offset 3, then its kernel-version probe treats that entry as a mapped linux_banner address. The original ELF symbol value is zero.

REA constructs LayoutELF at bridge/pwntools/layout_impl.py:170, so that heuristic raises before layout extraction. bridge/pwntools/decoder_runtime.py:52 and src/native/pwntools/PwntoolsDecoder.ts:442 preserve it as a generic decoder failure. This report concerns successful supported-object inspection, rather than error wording alone.

Additional context

Prepared with AI assistance and independently reproduced by a separate verifier. The submitter inspected the stored CLI/control output, direct upstream traceback, diagnostic probe and current source. NOT_ENOUGH_INFO: last known good version and introducing commit are unknown.

Related #5401 concerns missing-file/directory diagnostics in inspect-with-objdump; closed #3055 concerns unconfigured Python guidance. Neither covers a configured decoder rejecting this valid object. Open #4871 expands ELF architecture admission but retains the constructor path that runs this probe.

Related ELF reports: #5715 concerns the independent IKCFG_ST embedded-config scan; #5716 concerns classifying malformed program-header offsets. This report requires successful ET_REL inspection with the original undefined symbol and relocation identities. Disabling the kernel-version probe removes this trigger in direct parsing without repairing either sibling behavior.

Originally created by @coygeek on GitHub (Oct 20, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5717 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Native analysis or decompilation ### Observed behavior `inspect-binary-layout` returns `execution_failure` and no layout Evidence for a compiler-generated ELF64 x86-64 relocatable object referencing the undefined symbol `linux_banner`. An otherwise equivalent object referencing `ordinary_banner` succeeds. An independent verifier executed each CLI case once at the baseline below; this submission retains that attribution rather than claiming another runtime replay. ### Reproduction From the built source checkout on Linux x64, with `REA_PWNTOOLS_PYTHON` set to the absolute executable of the caller-supplied pinned Python environment: ```sh work_dir="$(mktemp -d)" pwn_python="$REA_PWNTOOLS_PYTHON" mkdir -p "$work_dir/home" "$work_dir/cfg" "$work_dir/data" \ "$work_dir/cache" "$work_dir/state" "$work_dir/temp" cat > "$work_dir/module.c" <<'C' extern const char linux_banner[]; const char *module_banner(void) { return linux_banner; } C sed 's/linux_banner/ordinary_banner/g' "$work_dir/module.c" > "$work_dir/control.c" gcc -O1 -c "$work_dir/module.c" -o "$work_dir/module.o" gcc -O1 -c "$work_dir/control.c" -o "$work_dir/control.o" inspect_object() { env -i PATH="$PATH" HOME="$work_dir/home" XDG_CONFIG_HOME="$work_dir/cfg" \ XDG_DATA_HOME="$work_dir/data" XDG_CACHE_HOME="$work_dir/cache" \ XDG_STATE_HOME="$work_dir/state" TMPDIR="$work_dir/temp" \ REA_LOG_LEVEL=silent REA_PWNTOOLS_PYTHON="$pwn_python" \ node scripts/rea.mjs inspect-binary-layout "$1" --json } for object in module control; do readelf -aW "$work_dir/$object.o" objdump -h -x "$work_dir/$object.o" nm "$work_dir/$object.o" inspect_object "$work_dir/$object.o" > "$work_dir/$object.json" printf '%s exit: %s\n' "$object" "$?" done cat "$work_dir/module.json" ``` The verifier ran equivalent commands with isolated HOME/XDG/TMPDIR directories and `env -i`. All three binutils readers exited 0 for both objects; REA exited 1 for `module.o` and 0 for the control. The fixtures were inspected without executing them. ### Expected behavior Return layout Evidence for this supported object, retaining the original sections, symbol-table identities and section-relative relocations. `linux_banner` must remain undefined with value zero. Its spelling does not make the relocatable object a mapped kernel image. Contract: [docs/binary-diagnostics.md](https://github.com/morluto/rea/blob/9d8e7803326a382cbbb3ffdb900f5e93e5442d68/docs/binary-diagnostics.md) supports Linux x64 ELF64 x86-64 little-endian EXEC/DYN/REL, undefined symbol values and section-relative relocations; `src/contracts/native/binaryDiagnosticsToolContracts.ts:50` exposes the offline layout operation. ### Impact and scope P2: a bounded compatibility defect prevents the entire supported offline layout inspection for this symbol reference. The ordinary-symbol control succeeds, returning 12 sections, 5 symbols and 2 relocations. Broader kernel-module coverage, other architectures and MCP were not tested. Independent binutils inspection works but does not return REA Evidence; no REA workaround preserving this artifact was verified. Renaming the symbol changes the analyzed bytes. ### REA version `rea-agents` 6.7.0, source baseline `9d8e7803326a382cbbb3ffdb900f5e93e5442d68`. Verified at baseline; main source-checked only at `84c89d1107cda017509bc3cd851573d073f9906d`. No intervening commits change the cited docs, contract, bridge files or TypeScript decoder; the package lock is unchanged. No fresh main runtime replay was performed. ### Runtime and platform Observed reproduction: Linux amd64 container, Node.js v24.22.0; gcc 12.2.0; caller-supplied pwntools 4.15.0, pyelftools 0.33 and Unicorn 2.1.2. Submission host, not the reproduction platform: Node.js v26.12.0; macOS 27.0.1; arm64. Hopper/Ghidra are not involved. ### Target and artifact context Self-built ELF64 little-endian x86-64 ET_REL object with no program headers. Its symbol-table entry 4 is GLOBAL/UND `linux_banner`, value zero; a PC-relative relocation references it. The control changes only the symbol spelling in the C source before recompilation. ### Interface CLI ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence Observed failing CLI subset (private snapshot operand omitted): ```json { "code": "execution_failure", "retryable": false, "details": { "provider_id": "pwntools-elf", "operation": "inspect_binary_layout", "diagnostics": { "phase": "decoder", "failure_kind": "decoder" } } } ``` The diagnostic reason begins `PwnlibException: Address 0x3 is not contained in LayoutELF`; the top-level message recommends `rea doctor`. Direct unchanged pwntools `ELF(path, checksec=False)` also fails for the same object, with `_populate_kernel_version` → `string` → `read` in its traceback, and succeeds for the control. In a separate scratch-only diagnostic process, disabling only the upstream kernel-version probe allows parsing to finish: its convenience symbol map has `linux_banner: 3` and `got.linux_banner: 3`, while the original symbol table still has `SHN_UNDEF` and `st_value: 0`. This is causal evidence, not a fix or successful public CLI restoration. ### Typed outcome or recovery expected Exit 0 with layout Evidence for the same artifact digest, preserving `linux_banner` as `SHN_UNDEF`, value zero, undefined value meaning and its original table/entry indices, plus the original relocation identities. Preserve control success. Translating the exception to an invalid-format refusal or suppressing the symbol would still reject or misrepresent supported input. ### Analysis or suspected cause Source-derived explanation supported by the direct traceback: the exception originates in upstream [Gallopsled/pwntools](https://github.com/Gallopsled/pwntools) 4.15.0, in the caller-supplied pinned dependency environment. Pwntools skips undefined entries in its normal symbol map, creates a synthetic GOT convenience entry at relocation offset 3, then its kernel-version probe treats that entry as a mapped `linux_banner` address. The original ELF symbol value is zero. REA constructs `LayoutELF` at `bridge/pwntools/layout_impl.py:170`, so that heuristic raises before layout extraction. `bridge/pwntools/decoder_runtime.py:52` and `src/native/pwntools/PwntoolsDecoder.ts:442` preserve it as a generic decoder failure. This report concerns successful supported-object inspection, rather than error wording alone. ### Additional context Prepared with AI assistance and independently reproduced by a separate verifier. The submitter inspected the stored CLI/control output, direct upstream traceback, diagnostic probe and current source. NOT_ENOUGH_INFO: last known good version and introducing commit are unknown. Related #5401 concerns missing-file/directory diagnostics in `inspect-with-objdump`; closed #3055 concerns unconfigured Python guidance. Neither covers a configured decoder rejecting this valid object. Open #4871 expands ELF architecture admission but retains the constructor path that runs this probe. Related ELF reports: #5715 concerns the independent `IKCFG_ST` embedded-config scan; #5716 concerns classifying malformed program-header offsets. This report requires successful ET_REL inspection with the original undefined symbol and relocation identities. Disabling the kernel-version probe removes this trigger in direct parsing without repairing either sibling behavior.
Author
Owner

@matbrgz commented on GitHub (Oct 21, 2026):

Cross-referencing with canonical issue #5715 (inspect-binary-layout fails on a valid ELF containing IKCFG_ST) and sibling ELF binary layout reports #5716, #5718.

Consolidated under Cluster CC (ELF Binary Layout Inspection & Section Allocation Bounds) in tracker #4330.

<!-- gh-comment-id:6304918788 --> @matbrgz commented on GitHub (Oct 21, 2026): Cross-referencing with canonical issue #5715 (`inspect-binary-layout fails on a valid ELF containing IKCFG_ST`) and sibling ELF binary layout reports #5716, #5718. Consolidated under **Cluster CC (ELF Binary Layout Inspection & Section Allocation Bounds)** in tracker #4330.
Author
Owner

@coygeek commented on GitHub (Oct 24, 2026):

Checked resolved on main at d87e73f2db.

The original linux_banner relocatable object and ordinary_banner control both succeeded through the production decoder and public CLI on Linux x64 with pwntools 4.15.0. The banner remains SHN_UNDEF, value 0x0, and value_meaning: "undefined", retaining its original symbol-table index 10 and entry index 4. Its relocation retains that same symbol identity and section-relative target. Those facts were checked against the original ELF tables, and input bytes remained unchanged. The adapter disables the unrelated kernel-version heuristic; no target object was executed.

Relevant implementation: layout_impl.py, layout_impl.py.

Closing as completed on main.

<!-- gh-comment-id:6380753263 --> @coygeek commented on GitHub (Oct 24, 2026): Checked resolved on `main` at d87e73f2db50be72d33a4b3c7199af35518b441c. The original `linux_banner` relocatable object and `ordinary_banner` control both succeeded through the production decoder and public CLI on Linux x64 with pwntools 4.15.0. The banner remains `SHN_UNDEF`, value `0x0`, and `value_meaning: "undefined"`, retaining its original symbol-table index 10 and entry index 4. Its relocation retains that same symbol identity and section-relative target. Those facts were checked against the original ELF tables, and input bytes remained unchanged. The adapter disables the unrelated kernel-version heuristic; no target object was executed. Relevant implementation: [layout_impl.py](https://github.com/morluto/rea/blob/d87e73f2db50be72d33a4b3c7199af35518b441c/bridge/pwntools/layout_impl.py#L166), [layout_impl.py](https://github.com/morluto/rea/blob/d87e73f2db50be72d33a4b3c7199af35518b441c/bridge/pwntools/layout_impl.py#L187). Closing as completed on main.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3468
No description provided.