ssh/tailssh: close tty on session close

We were only closing on side of the pty/tty pair.
Close the other side too.

Thanks to @fritterhoff for reporting and debugging the issue!

Fixes #8119

Signed-off-by: Maisem Ali <maisem@tailscale.com>
This commit is contained in:
Maisem Ali
2023-05-17 12:18:23 -07:00
committed by Maisem Ali
parent 03e848e3b5
commit 0ca8bf1e26
2 changed files with 24 additions and 11 deletions

View File

@@ -452,7 +452,7 @@ func (ss *sshSession) launchProcess() error {
return ss.startWithStdPipes()
}
ss.ptyReq = &ptyReq
pty, err := ss.startWithPTY()
pty, tty, err := ss.startWithPTY()
if err != nil {
return err
}
@@ -461,10 +461,13 @@ func (ss *sshSession) launchProcess() error {
// dup.
ptyDup, err := syscall.Dup(int(pty.Fd()))
if err != nil {
pty.Close()
tty.Close()
return err
}
go resizeWindow(ptyDup /* arbitrary fd */, winCh)
ss.tty = tty
ss.stdin = pty
ss.stdout = os.NewFile(uintptr(ptyDup), pty.Name())
ss.stderr = nil // not available for pty
@@ -544,17 +547,16 @@ var opcodeShortName = map[uint8]string{
}
// startWithPTY starts cmd with a pseudo-terminal attached to Stdin, Stdout and Stderr.
func (ss *sshSession) startWithPTY() (ptyFile *os.File, err error) {
func (ss *sshSession) startWithPTY() (ptyFile, tty *os.File, err error) {
ptyReq := ss.ptyReq
cmd := ss.cmd
if cmd == nil {
return nil, errors.New("nil ss.cmd")
return nil, nil, errors.New("nil ss.cmd")
}
if ptyReq == nil {
return nil, errors.New("nil ss.ptyReq")
return nil, nil, errors.New("nil ss.ptyReq")
}
var tty *os.File
ptyFile, tty, err = pty.Open()
if err != nil {
err = fmt.Errorf("pty.Open: %w", err)
@@ -568,7 +570,7 @@ func (ss *sshSession) startWithPTY() (ptyFile *os.File, err error) {
}()
ptyRawConn, err := tty.SyscallConn()
if err != nil {
return nil, fmt.Errorf("SyscallConn: %w", err)
return nil, nil, fmt.Errorf("SyscallConn: %w", err)
}
var ctlErr error
if err := ptyRawConn.Control(func(fd uintptr) {
@@ -615,10 +617,10 @@ func (ss *sshSession) startWithPTY() (ptyFile *os.File, err error) {
return
}
}); err != nil {
return nil, fmt.Errorf("ptyRawConn.Control: %w", err)
return nil, nil, fmt.Errorf("ptyRawConn.Control: %w", err)
}
if ctlErr != nil {
return nil, fmt.Errorf("ptyRawConn.Control func: %w", ctlErr)
return nil, nil, fmt.Errorf("ptyRawConn.Control func: %w", ctlErr)
}
cmd.SysProcAttr = &syscall.SysProcAttr{
Setctty: true,
@@ -642,7 +644,7 @@ func (ss *sshSession) startWithPTY() (ptyFile *os.File, err error) {
if err = cmd.Start(); err != nil {
return
}
return ptyFile, nil
return ptyFile, tty, nil
}
// startWithStdPipes starts cmd with os.Pipe for Stdin, Stdout and Stderr.