Skip to content

[LOW] Close duplex pipe ends when launch fails - #203

Open
OskarEichler wants to merge 1 commit into
enkessler:masterfrom
OskarEichler:codex/close-duplex-pipe
Open

OskarEichler wants to merge 1 commit into
enkessler:masterfrom
OskarEichler:codex/close-duplex-pipe

Conversation

@OskarEichler

@OskarEichler OskarEichler commented Aug 29, 2026 •

Copy link
Copy Markdown

Summary

Closes both internally created duplex pipe ends when Process.spawn raises, preventing each failed launch from leaking two descriptors in the parent.

Security impact

LOW: when an application enables duplex mode and repeatedly attempts an attacker-influenced or unavailable executable, every failed launch retains two file descriptors until process exit. Repeated failures can exhaust the parent's descriptor limit and deny unrelated file, socket, and process operations.

The ensure block closes only the gem-owned pipe ends when no child PID was assigned. Successful launch behavior is unchanged.

Reproduction

On 5.1.0, 50 failed duplex launches of a missing executable grow /dev/fd by exactly 100 descriptors. The same bounded reproduction reports zero growth on this branch.

Verification

  • Ruby 4.0.6 upstream suite: 70 examples, 0 failures.
  • Focused 50-launch descriptor-count reproduction: baseline +100, fixed +0.
  • Original launch error type remains ChildProcess::LaunchError.
  • git diff --check passes.

All Ruby-backed checks used rbenv.

Limitations

The descriptor count reproduction was run on macOS. Windows, JRuby, and TruffleRuby were not run locally.

Breaking changes

None. The patch only closes internal resources after a failed spawn.

@OskarEichler OskarEichler changed the title Close duplex pipe ends when launch fails [LOW] Close duplex pipe ends when launch fails Sep 3, 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.

1 participant