Skip to content

fix(fspy): fail an exec of an empty path like the untraced call - #896

Merged
wan9chi merged 2 commits into
fix/fspy-exec-absolute-no-allocfrom
fix/fspy-exec-empty-path
Oct 26, 2026
Merged

wan9chi merged 2 commits into
fix/fspy-exec-absolute-no-allocfrom
fix/fspy-exec-empty-path

Conversation

@wan9chi

@wan9chi wan9chi commented Oct 26, 2026

Copy link
Copy Markdown
Member

Motivation

An exec of an empty path fails with ENOENT before the kernel looks anything up. Under fspy:

Entry point, path "" Untraced Traced, before
execve, execv, execl, execle, posix_spawn ENOENT the program aborts: shebang parsing reports "" as read, and making it absolute fails (Failed to get cwd)
execvp, execlp, execvpe, posix_spawnp ENOENT ENOENT (the PATH search already rejects "")
execveat(dirfd, "", …) without AT_EMPTY_PATH (Linux) ENOENT resolves "" against dirfd and tries to run what it refers to: EISDIR for AT_FDCWD, with the directory reported as read

Change

  • Exec::resolve fails an empty program with ENOENT before anything else, as execve and libc's PATH search do, so nothing is read or reported.
  • The execveat interposer forwards an empty path without AT_EMPTY_PATH to the real call. With AT_EMPTY_PATH it still resolves dirfd as before.
  • crates/fspy/tests/exec_empty_path.rs makes every call untraced in the test process, then traced, and asserts the results are equal and that the working directory isn't reported. On musl, seccomp tracking still reports the directory an empty path is relative to, so that check is skipped there; the errno comparison still runs.

🤖 Generated with Claude Code

@wan9chi
wan9chi force-pushed the fix/fspy-exec-empty-path branch from 17018aa to 5719bbf Compare October 26, 2026 07:42
@wan9chi
wan9chi added this pull request to stack #895 October 26, 2026 07:42
@wan9chi wan9chi added the ci: full Run the slow CI jobs (macOS x64, musl) on this pull request label Oct 26, 2026
@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

fspy benchmark

linux

dynamic/launch             change  +0.28%  [ -6.44% ..  +6.61%]  overhead   +60.37%
dynamic/access             change  -0.40%  [ -5.58% ..  +4.26%]  overhead   +19.62%
dynamic/access-relative    change  -2.53%  [-14.33% ..  +3.02%]  overhead   +62.29%
dynamic/access-contended   change  -2.35%  [-11.98% ..  +6.72%]  overhead    +5.92%
static/launch              change  +1.08%  [ -5.55% ..  +7.03%]  overhead  +195.82%
static/access              change  +1.35%  [ -5.71% .. +25.89%]  overhead +1104.25%
static/access-relative     change  +0.87%  [ -3.24% .. +17.71%]  overhead +1680.90%
static/access-contended    change  -0.19%  [ -8.37% .. +13.95%]  overhead +1081.84%

macos

dynamic/launch             change  -0.03%  [ -3.93% ..  +4.77%]  overhead  +227.65%
dynamic/access             change  -0.34%  [-50.34% ..  +6.55%]  overhead    +0.40%
dynamic/access-relative    change  +0.91%  [ -3.66% ..  +3.50%]  overhead  +263.17%
dynamic/access-contended   change  +2.78%  [ -8.00% .. +38.37%]  overhead    +2.77%

windows

dynamic/launch             change  +0.15%  [ -1.43% ..  +1.89%]  overhead   +25.16%
dynamic/access             change  +0.00%  [ -0.38% ..  +0.56%]  overhead    +0.95%
dynamic/access-relative    change  +0.19%  [ -0.37% ..  +0.56%]  overhead    +1.12%
dynamic/access-contended   change  +0.13%  [ -0.36% ..  +0.54%]  overhead    +1.46%

@wan9chi
wan9chi force-pushed the fix/fspy-exec-empty-path branch from 5719bbf to 741989a Compare October 26, 2026 07:59
wan9chi and others added 2 commits October 26, 2026 17:00
execve, execv, execl, execle and posix_spawn with an empty path aborted
traced programs: shebang parsing reported the empty path as read, and
making it absolute failed. Without fspy the call fails with ENOENT
before the kernel looks anything up. `Exec::resolve` now fails an empty
program with ENOENT first, so nothing is read or reported.

execveat with an empty path and without AT_EMPTY_PATH resolved the path
against dirfd and tried to run what dirfd refers to (EISDIR for
AT_FDCWD). It now forwards to the real call, which fails with ENOENT.

The test makes each call untraced and traced and compares the results.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@wan9chi
wan9chi force-pushed the fix/fspy-exec-empty-path branch from 741989a to f5eee7a Compare October 26, 2026 08:01
@wan9chi
wan9chi merged commit 321fabb into main Oct 26, 2026
21 of 36 checks passed
@wan9chi
wan9chi deleted the fix/fspy-exec-empty-path branch October 26, 2026 09:06
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.

1 participant