[android] bound the SSH handshake with a deadline

DialContext limited only the TCP establishment, so a peer that accepted
the connection and then stayed silent left gossh.NewClientConn blocking
forever and the terminal stuck on "Connecting".

Set the socket deadline from the dial context before the handshake and
clear it on success, so the handshake shares the dial timeout instead of
being able to hang. Verified against a silent listener: the connect now
returns i/o timeout instead of blocking.
This commit is contained in:
Zoltán Papp
2026-08-11 16:50:22 +02:00
parent 6a83476831
commit cc0702396c

View File

@@ -435,6 +435,16 @@ func (s *SSHClient) dialAndHandshake(host string, port int, clientConfig *gossh.
return fmt.Errorf("dial %s: %w", addr, err)
}
// DialContext bounds only the TCP establishment; without a deadline on the
// socket a peer that accepts and then goes silent blocks the handshake
// forever.
if deadline, ok := ctx.Deadline(); ok {
if err := conn.SetDeadline(deadline); err != nil {
closeQuiet(conn, "conn after deadline error")
return fmt.Errorf("set handshake deadline: %w", err)
}
}
sshConn, chans, reqs, err := gossh.NewClientConn(conn, addr, clientConfig)
if err != nil {
if cerr := conn.Close(); cerr != nil {
@@ -443,6 +453,11 @@ func (s *SSHClient) dialAndHandshake(host string, port int, clientConfig *gossh.
return fmt.Errorf("ssh handshake: %w", err)
}
if err := conn.SetDeadline(time.Time{}); err != nil {
closeQuiet(sshConn, "ssh conn after deadline clear error")
return fmt.Errorf("clear handshake deadline: %w", err)
}
s.mu.Lock()
s.sshClient = gossh.NewClient(sshConn, chans, reqs)
listener := s.listener