Files
Neil 696a5107f0 fix(ssh): stop a failed lsof from proving a relay endpoint exited
The incumbent probe printed `HOLDERS_SOURCE=lsof` before running `lsof`, then
discarded its exit status and stderr. Any `lsof` that ended with empty stdout for
a reason other than "nobody holds it" therefore parsed as verdict `exited`,
evidence `no-holder`, `holdersEnumerable: true` — a positive claim of absence the
host never made. `classifySupersededRelay` turns that claim into `rm -f` on the
socket inode, so it can unlink a path a live relay is still holding.

Measured on Debian 12 against a real NFS mount whose server is blackholed:

  condition                    wall      exit  stdout  stderr        holder found
  no network mounts            141ms     0     pid     -             yes
  NFS healthy                  143ms     0     pid     -             yes
  NFS wedged (hard)            >120s     KILL  -       -             no (blocked)
  NFS wedged, -w               >120s     KILL  -       -             no (blocked)
  NFS wedged, -S 2             >120s     KILL  -       -             no (blocked)
  any host, -b                 2ms       1     -       status error  no (WRONG)
  nothing holds it             fast      1     -       -             n/a (correct)

Two things follow. `-w` and `-S` do not address the blocking, and `-b` reports no
holder for a socket a live process is holding even on a host with no network
mounts, so neither is a fix. And because `-t` exits 1 both for "nobody holds it"
and for "could not answer", only the diagnostics separate the two.

Today the block is what protects us: the probe dies before `PROBE_END`, the
sentinel check fails, and the verdict is `unverifiable`. That safety is
accidental, and it is spent the moment anyone bounds the probe — a `timeout`
around the wedged case yields empty stdout and empty stderr, which the old script
read as `exited`.

So the script now decides `HOLDERS_SOURCE` after `lsof` has run: it merges stderr
into stdout, treats any non-numeric word or any exit outside lsof's own 0/1 as a
failure to answer, and emits `HOLDERS_SOURCE=error` — which the parser already
reads as not enumerable, hence `unverifiable`. Pids lsof did report are still
honoured, and an absent path stays exempt, so healthy hosts are unchanged and the
reap never becomes more permissive. Per docs/reference/ssh-execution-boundary.md,
a probe that could not answer is `unverifiable`, never `exited`.

This does not make husks reapable on a host with a wedged mount — lsof still
blocks there and the verdict stays `unverifiable`. Leaking husks is the correct
failure mode; unlinking a held socket is not. A `/proc/net/unix` + `/proc/*/fd`
enumeration answered that host correctly in 45ms and is the Linux-only follow-up.
2026-09-13 22:48:13 -07:00
..