Skip to content

fix(fspy): allocate a slot for the NULL terminator in execl with 32+ arguments - #865

Merged
wan9chi merged 2 commits into
voidzero-dev:mainfrom
tlq5l:fix/fspy-execl-argv-terminator
Oct 26, 2026
Merged

wan9chi merged 2 commits into
voidzero-dev:mainfrom
tlq5l:fix/fspy-execl-argv-terminator

Conversation

@tlq5l

@tlq5l tlq5l commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #699

Motivation

with_argv builds the argv array for execl, execlp and execle. With 32 or more arguments it takes the heap branch, which allocated exactly argc slots and then wrote the closing NULL at out[argc]. That index panicked inside an extern "C" interposer, which aborted the traced process.

Change

  • Allocate argc + 1 slots in the heap branch, so the NULL terminator has room.
  • New test crates/fspy/tests/execl_many_args.rs calls execl with 40 arguments under fspy and checks the child exits normally. It aborts without the fix.
  • Changelog entry under Unreleased.

Ran live: a C program that calls execl("/bin/echo", "echo", "a1", ..., "a40", NULL), run as a cached task with vt run many. On a clean build of main it printed index out of bounds: the len is 41 but the index is 41 and fatal runtime error: failed to initiate panic; on a clean build of this branch it printed a1 a2 ... a40.

@tlq5l
tlq5l force-pushed the fix/fspy-execl-argv-terminator branch from 6e4f8df to 81b6f34 Compare October 19, 2026 22:27
…arguments

Fixes voidzero-dev#699

The heap branch of `with_argv` allocated exactly `argc` slots, then wrote
the closing NULL at `out[argc]`. That panicked inside an `extern "C"`
interposer, which aborted the traced process. Allocate `argc + 1` slots.

Co-authored-by: DeepSeek V4.1 Flash <noreply@deepseek.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@tlq5l
tlq5l force-pushed the fix/fspy-execl-argv-terminator branch from 81b6f34 to d6a4a1a Compare October 21, 2026 17:46
@wan9chi wan9chi added the ci: full Run the slow CI jobs (macOS x64, musl) on this pull request label Oct 26, 2026
@wan9chi
wan9chi merged commit 194ee9c into voidzero-dev:main Oct 26, 2026
20 checks passed
@wan9chi

wan9chi commented Oct 26, 2026

Copy link
Copy Markdown
Member

Thank you!

wan9chi added a commit that referenced this pull request Oct 26, 2026
…891)

## Motivation

`execl`, `execlp` and `execle` pass their arguments as a variadic list,
so the interposer has to build an argv array before it can handle the
exec. It used a 32-slot stack array, fell back to libc `malloc` for
longer lists, and failed with `E2BIG` past a hardcoded 4096 arguments.
That split is where #865's out-of-bounds write lived, and the `malloc`
fallback isn't async-signal-safe: exec may run in the child of `fork()`,
where malloc's lock may be held by a thread that no longer exists.

## Change

- A small `collect_argv` pushes `arg` and the variadic arguments, up to
and including the NULL, into an `allocator_api2::vec::Vec` in the call's
`pooled_bump()`, and leaves the `VaList` where `execle` reads `envp`.
- Each of the three interposers creates one bump and passes it to both
`collect_argv` and `handle_exec`, as `execveat` already does.
- `with_argv.rs` is removed along with the stack/heap split and the
4096-argument limit; the real `execve` reports `E2BIG` instead.

The rest of the exec path still allocates through libc `malloc`
(`RawExec::to_exec`/`from_exec`, `fexecve`); the PR stacked on this one
removes that.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci: full Run the slow CI jobs (macOS x64, musl) on this pull request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fspy_preload_unix: execl with 32+ arguments aborts on an out-of-bounds NULL terminator write

2 participants