tailscale: SSH and SCP commands to tailscale ssh endpoints do not return correct error / success codes

What is the issue?

Issue found while testing the mutagen file synchronization tool with a server where I use tailscale --ssh.

That program attempts to run a remote agent via a ssh command ssh user@tailscalehost agent and handles the 127 POSIX error code for when the command does not exist. tailscale ssh just returns an exit code of 1, although I think it writes the correct exit code in stderr. (see below).

Aside from that, a normal (and successful) scp command to a tailscale --ssh host also returns EOF with exit code 1 on my machine.

Local ssh version on arch linux: core/openssh 9.1p1-1 [installed].

Steps to reproduce

sebi@archdesktop ~/devel/mutagen $ ssh deckbox@a1 boguscommand
/bin/bash: boguscommand: command not found
exit status 127
sebi@archdesktop ~/devel/mutagen $ echo $?
1
sebi@archdesktop ~/devel/mutagen $ ssh deckbox@a1.bifolia.net boguscommand
bash: boguscommand: command not found
sebi@archdesktop ~/devel/mutagen $ echo $?
127
sebi@archdesktop ~/devel/mutagen $ scp README.md deckbox@a1.bifolia.net:
README.md                                                                     100% 5058   189.3KB/s   00:00    
sebi@archdesktop ~/devel/mutagen $ echo $?
0
sebi@archdesktop ~/devel/mutagen $ scp README.md deckbox@a1:
README.md                                                                     100% 5058   158.6KB/s   00:00    
EOF
sebi@archdesktop ~/devel/mutagen $ echo $?
1

Are there any recent changes that introduced the issue?

No response

OS

Linux

OS version

Ubuntu 18.04

Tailscale version

1.32.1

Bug report

BUG-b56db22c2e3ba12f87fd30ea839658e217bf7311f497485a617add42aac24bdb-20221025090330Z-0104a27f39e6c969

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 15 (14 by maintainers)

Commits related to this issue

Most upvoted comments

So this seems to do it:

diff --git a/ssh/tailssh/incubator.go b/ssh/tailssh/incubator.go
index 5c975046..42568192 100644
--- a/ssh/tailssh/incubator.go
+++ b/ssh/tailssh/incubator.go
@@ -283,7 +283,12 @@ func beIncubator(args []string) error {
                        Foreground: true,
                }
        }
-       return cmd.Run()
+       err = cmd.Run()
+       if ee, ok := err.(*exec.ExitError); ok {
+               code := ee.ProcessState.ExitCode()
+               os.Exit(code)
+       }
+       return err
 }
 
 // launchProcess launches an incubator process for the provided session.

ah! Nice.

be-child is swallowing the error:

root@host:~# cat failure
#!/bin/bash
exit 7
root@host:~# tailscaled be-child ssh --uid=0 --gid=0 --groups=0 --cmd=/root/failure ; echo $?
exit status 7
1