Kristoffer Dalby c1d20a3b8c ssh/tailssh: bypass /usr/bin/login on darwin for non-TTY exec sessions
On macOS the incubator went through /usr/bin/login -pq <user> <shell>
-c <cmd> for any session, including non-TTY 'ssh host cmd' exec
sessions. /usr/bin/login does not propagate the child command's exit
status when invoked this way: it exits 0 once the child has been
spawned, so 'ssh mac exit 42' returned 0 instead of 42 and
'ssh mac /nonexistent/binary' returned 0 instead of 127. The
exit-status frame ordering fix in this branch is still required (the
server has to send the right frames in the right order), but it is
not sufficient on its own when the value being sent is wrong.

For interactive shells (hasTTY) login still gives us the desired
PAM 'remote' session and utmpx accounting, and exit-code propagation
is not user-observable, so the login path is kept. For non-TTY
command exec sessions we now fall through to handleSSHInProcess,
which uses dropPrivileges + cmd.Run + os.Exit(code) — the same path
Linux already uses for non-TTY sessions, and the path that produces
correct exit codes in the integration tests.

Verified against the macOS CI logs from run 25326829991: the artifact
shows the server sending exit-status 0 from /usr/bin/login -pq
... /bin/bash -c 'exit 42', confirming the diagnosis. Verified on
Linux that the fall-through path produces the right exit codes
(integration tests pass 5x consecutively on the full incubator path
including drop-privileges).

Fixes #18256

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2026-05-04 15:18:47 +00:00
..
2026-04-10 10:48:50 -07:00