fix(tracer): exec-check ptrace binary, not just file existence (P0-3)#86
Open
christophergeyer wants to merge 1 commit intocg/preload-event-cleanupfrom
Open
fix(tracer): exec-check ptrace binary, not just file existence (P0-3)#86christophergeyer wants to merge 1 commit intocg/preload-event-cleanupfrom
christophergeyer wants to merge 1 commit intocg/preload-event-cleanupfrom
Conversation
5 tasks
The ptrace tracer was treated as "available" anywhere a path-existence
check returned True, even when the binary was a wrong-arch ELF that
produced ENOEXEC at exec time. The eval team's P0-3 reproducer (an
x86_64 ptrace tracer in an aarch64 wheel) confirmed this on Mac too:
`roar tracer status` listed ptrace as ready, runtime auto-selection
picked it, then the actual run failed with "Exec format error" while
roar had already committed to ptrace as the chosen backend.
`roar tracer check --backend ptrace` and `--backend auto` were already
exec-based — they call the binary's `--preflight --json` mode and
catch OSError(ENOEXEC). The bug was elsewhere:
1. `roar tracer status` printed `ptrace: <path>` with no readiness
check, while ebpf and preload showed their ready state.
2. Runtime auto-selection in `_resolve_backend_candidate` only
called `_find_ptrace_tracer` (file-exists), then returned the
candidate without exec-checking — inconsistent with the ebpf
and preload branches which both gate on `*_is_ready`.
3. `_backend_ready_non_auto` had the same existence-only shortcut.
Fix: add `ptrace_readiness(path)` mirroring `preload_readiness` —
exec the binary's `--preflight --json` once (cached via `@cache`),
parse the JSON, surface either the binary's own summary or the OS
error. Wire it into `_resolve_backend_candidate`, `_backend_ready_non_auto`,
and `_print_status` so all three call sites consistently exec the
binary before declaring it usable.
Tests:
- tracer_backends: ptrace_is_ready happy path, ENOEXEC catch, and
binary-reports-its-own-failure path; auto-mode skips an unready
ptrace and falls through to "no usable tracer found"
- tracer_selection: existing auto-skips-ebpf-and-picks-ptrace test
now mocks _ptrace_is_ready as ready (the gate it didn't have
before); new test pins the regression — auto must skip ptrace
when its readiness check fails
Verification:
- pytest integration: 96 passed
- pytest unit: 1387 passed (was 1382 + 5 new)
- ruff check + format / mypy: clean
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
66e45c9 to
0e673ef
Compare
b177593 to
feefb7e
Compare
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.
Summary
The ptrace tracer was treated as "available" anywhere a path-existence check returned True, even when the binary was a wrong-arch ELF that produced ENOEXEC at exec time. P0-3 reproduction on Mac (and reproducible on this aarch64 box by replacing the binary with non-ELF content):
roar tracer check --backend ptraceand--backend autowere already exec-based (they go through the binary's--preflight --jsonand catchOSError(ENOEXEC)). The bug surfaced in three other places that all reduced ptrace's readiness to file-existence:roar tracer status— printedptrace: <path>with no readiness check, while ebpf/preload showed their ready state_resolve_backend_candidate) — only called_find_ptrace_tracer, returned the candidate without exec-checking_backend_ready_non_auto— same existence-only shortcutFix
Add
ptrace_readiness(path)mirroringpreload_readiness: exec the binary's--preflight --jsononce (cached via@cache), parse the JSON, surface either the binary's own failure summary or the OS error. Wire into all three call sites.After-fix output (with broken ptrace binary)
Test plan
tracer_backendsunit tests: ptrace_is_ready happy path; ENOEXEC catch; binary-reports-its-own-failure path; auto-mode skips an unready ptrace and falls throughtracer_selectionunit test: auto must skip ptrace when its readiness check fails (regression for the existence-only bug)test_auto_skips_unready_ebpf_and_selects_ptraceupdated to mock_ptrace_is_ready(the gate it didn't have before)--backend autocorrectly falls through to preloadStacks on #85.
🤖 Generated with Claude Code