From 32aaa2eae11e9598889e86f1942264ed245f854a Mon Sep 17 00:00:00 2001 From: sergiu128 Date: Tue, 26 Nov 2024 19:36:56 +0100 Subject: [PATCH] Do not ignore SO_ERROR value on connect Otherwise we will mark the connection as successful and a subsequent read/write will return EOF. In reality, the connect syscall failed. Checking the return value of Getsockoptint(... SO_ERROR) will tell us whether the connect syscall succeeded. A return value of 0 means success - anything else can be interpreted by syscall.Errno and means failure. I was mislead into thinking the returned `err` from `Getsockoptint` is the actual socket error - in reality, it's whether the `getsockopt` syscall succeeded or not. - Golang src: https://github.com/golang/go/blob/04879acdebbb08bdca00356f043d769c4b4375ce/src/syscall/syscall_unix.go#L312 - Sanity check that uninit values are set to 0: https://go.dev/play/p/vCLjDd6WwL- - syscall.Errno is safe for any input value: https://cs.opensource.google/go/go/+/refs/tags/go1.23.3:src/syscall/syscall_unix.go;l=110 --- internal/socket_unix.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/internal/socket_unix.go b/internal/socket_unix.go index 62291622..a817a2e9 100644 --- a/internal/socket_unix.go +++ b/internal/socket_unix.go @@ -151,10 +151,13 @@ func connect(fd int, remoteAddr net.Addr, timeout time.Duration, opts ...sonicop return sonicerrors.ErrTimeout } - _, err = syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_ERROR) + socketErr, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_ERROR) if err != nil { return os.NewSyscallError("getsockopt", err) } + if socketErr != 0 { + return syscall.Errno(socketErr) + } } return nil