Skip to content

Commit 23f28b5

Browse files
JAORMXclaude
andcommitted
Fix SSH agent forwarding goroutine leak via missing half-close
When a guest process disconnects from the agent socket, io.Copy(channel, unixConn) returns but the channel write side stays open. The host's ServeAgent blocks reading the channel waiting for a request that never comes, and the guest's reverse copy blocks waiting for a response. Neither side ever closes, leaking both goroutines and a maxAgentConns semaphore slot. After 8 leaked connections (maxAgentConns), all new agent socket connections are rejected, breaking SSH agent forwarding for the rest of the session. Symptoms: git operations succeed for the first few minutes then fail with "Permission denied (publickey)". Fix: call channel.CloseWrite() after the guest->host copy finishes, signaling EOF to the host so ServeAgent returns and the full cleanup chain completes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 8a4bc2e commit 23f28b5

1 file changed

Lines changed: 1 addition & 0 deletions

File tree

guest/sshd/session.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,7 @@ func (s *Server) proxyAgentConnection(conn *ssh.ServerConn, unixConn net.Conn) {
513513
go func() {
514514
defer wg.Done()
515515
_, _ = io.Copy(channel, unixConn)
516+
_ = channel.CloseWrite() // Signal host that guest disconnected from agent socket.
516517
}()
517518
go func() {
518519
defer wg.Done()

0 commit comments

Comments
 (0)