diff --git a/protocol/tailscale/tailssh/session_platform.go b/protocol/tailscale/tailssh/session_platform.go index f0799218d..5d5c5b773 100644 --- a/protocol/tailscale/tailssh/session_platform.go +++ b/protocol/tailscale/tailssh/session_platform.go @@ -28,6 +28,7 @@ func (b *platformShellBackend) OpenSession(request shellRequest) (shellSession, return &platformShellSession{ session: session, master: master, + isPty: request.Term != "", }, nil } @@ -38,6 +39,7 @@ func (b *platformShellBackend) Close() error { type platformShellSession struct { session adapter.ShellSession master *os.File + isPty bool } func (s *platformShellSession) Read(p []byte) (int, error) { @@ -53,8 +55,10 @@ func (s *platformShellSession) Close() error { } func (s *platformShellSession) CloseWrite() error { - // The platform owns the master fd lifecycle; rely on Close for teardown. - return nil + if s.isPty { + return nil + } + return syscall.Shutdown(int(s.master.Fd()), syscall.SHUT_WR) } func (s *platformShellSession) Resize(rows, cols uint16) error { diff --git a/protocol/tailscale/tailssh/subprocess_unix.go b/protocol/tailscale/tailssh/subprocess_unix.go index 358609b71..f40c57c1d 100644 --- a/protocol/tailscale/tailssh/subprocess_unix.go +++ b/protocol/tailscale/tailssh/subprocess_unix.go @@ -41,6 +41,8 @@ func StartSocketpairProcess(shell string, args, env []string, dir string, uid, g if err != nil { return nil, nil, E.Cause(err, "socketpair") } + syscall.CloseOnExec(fds[0]) + syscall.CloseOnExec(fds[1]) childFile := os.NewFile(uintptr(fds[1]), "socketpair-child") cmd := exec.Command(shell) cmd.Args = args