Skip to content

Decide how honmoon run handles a network socket passed as stdio #72

Description

@amondnet

Follow-up from a review thread on #71: #71 (comment)

The gap

honmoon run on Linux spawns the child into an empty network namespace, and close_inherited_descriptors() closes every inherited descriptor so a leaked non-CLOEXEC socket cannot carry traffic out of it. That sweep deliberately starts at fd 3, because the child needs a stdin, stdout and stderr to be a usable command at all.

So if honmoon itself is launched with a connected network socket as one of those three, the child inherits it. A socket keeps its binding across unshare, so it stays a live channel to that peer — a real exception to the "reaches nothing over the network" claim.

Why #71 did not change behavior

The two obvious remedies are both user-visible behavior changes that a review-apply pass should not decide unilaterally:

  • Refuse to run when stdio is socket-valued — breaks a legitimate honmoon run whose output the operator deliberately wired to a socket.
  • Replace socket stdio with /dev/null — silently discards the child's output, which is arguably worse than the hole.

It is also not something the child can arrange for itself: it requires an operator to have already connected honmoon's stdio to a network peer, and the reachable surface is that one peer. That puts it in the same class as the filesystem-Unix-socket caveat (/var/run/docker.sock) the README already documents.

#71 therefore documents it in both places rather than changing behavior:

  • crates/honmoon-cli/src/isolate/linux.rs module doc
  • README.md, in the privilege / docker.sock paragraph

The decision to make

  1. Keep documenting only. Consistent with how the docker.sock caveat is handled today.
  2. Detect and warn. fstat stdio and, when S_ISSOCK, print a prominent stderr warning naming the bypass but still run. Consistent with how Isolation::Advisory already surfaces a weaker-than-expected posture rather than hard-failing.
  3. Detect and refuse. Fail closed, consistent with the README's position that a client which cannot use the proxy failing closed "is the correct default for a firewall". Would need an escape-hatch flag.

Option 2 looks like the best fit for this project's existing habit of stating weaknesses plainly rather than silently tolerating or hard-failing on them, but this is an author call.

Notes

  • Detection is cheap: fstat(fd) and test S_ISSOCK(st_mode), or getsockopt(fd, SOL_SOCKET, SO_TYPE, ...) succeeding.
  • A pipe to a socket is not affected — only a socket handed directly as fd 0, 1 or 2.
  • Related: TD-003 in .please/docs/tracks/tech-debt-tracker.md.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions