os/linux: return error on EALREADY for connect() and getsockoptError()

When a connected socket file descriptor on Linux is re-acquired
    after being closed, through fuzz testing, it appears that a
    subsequent attempt to establish a connection with the file
    descriptor causes EALREADY to be reported.

    Instead of panicking, choose to return error.ConnectionPending
    to allow for users to handle this fairly rare case.
This commit is contained in:
lithdew 2021-04-02 05:28:25 +09:00 committed by Isaac Freund
parent 83a2665772
commit 2bfc6d14d5

View File

@ -3254,6 +3254,9 @@ pub const ConnectError = error{
/// Connection was reset by peer before connect could complete.
ConnectionResetByPeer,
/// Socket is non-blocking and already has a pending connection in progress.
ConnectionPending,
} || UnexpectedError;
/// Initiate a connection on a socket.
@ -3294,7 +3297,7 @@ pub fn connect(sock: socket_t, sock_addr: *const sockaddr, len: socklen_t) Conne
EADDRNOTAVAIL => return error.AddressNotAvailable,
EAFNOSUPPORT => return error.AddressFamilyNotSupported,
EAGAIN, EINPROGRESS => return error.WouldBlock,
EALREADY => unreachable, // The socket is nonblocking and a previous connection attempt has not yet been completed.
EALREADY => return error.ConnectionPending,
EBADF => unreachable, // sockfd is not a valid open file descriptor.
ECONNREFUSED => return error.ConnectionRefused,
ECONNRESET => return error.ConnectionResetByPeer,
@ -3325,7 +3328,7 @@ pub fn getsockoptError(sockfd: fd_t) ConnectError!void {
EADDRNOTAVAIL => return error.AddressNotAvailable,
EAFNOSUPPORT => return error.AddressFamilyNotSupported,
EAGAIN => return error.SystemResources,
EALREADY => unreachable, // The socket is nonblocking and a previous connection attempt has not yet been completed.
EALREADY => return error.ConnectionPending,
EBADF => unreachable, // sockfd is not a valid open file descriptor.
ECONNREFUSED => return error.ConnectionRefused,
EFAULT => unreachable, // The socket structure address is outside the user's address space.