From e72898ad92a52a595d4733210483e9689cb5d390 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 5 Feb 2021 12:13:12 +0100 Subject: swrap: make swrap_accept() more resilient against races related to already disconnected sockets Callers of accept() expect to get ECONNABORTED instead of a disconnected socket. Even on Linux we have a potential race calling libc_getsockname() after accept(), so we map ENOTCONN to ECONNABORTED. We should do all syscalls in order to have peer and sockname, before doing in memory things like calling sockaddr_convert_from_un(). Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider --- src/socket_wrapper.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/socket_wrapper.c b/src/socket_wrapper.c index 5839a5c..d72b31f 100644 --- a/src/socket_wrapper.c +++ b/src/socket_wrapper.c @@ -3642,10 +3642,12 @@ static int swrap_accept(int s, ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen); #endif if (ret == -1) { - if (errno == ENOTSOCK) { + int saved_errno = errno; + if (saved_errno == ENOTSOCK) { /* Remove stale fds */ swrap_remove_stale(s); } + errno = saved_errno; return ret; } @@ -3654,6 +3656,23 @@ static int swrap_accept(int s, /* Check if we have a stale fd and remove it */ swrap_remove_stale(fd); + ret = libc_getsockname(fd, + &un_my_addr.sa.s, + &un_my_addr.sa_socklen); + if (ret == -1) { + int saved_errno = errno; + libc_close(fd); + if (saved_errno == ENOTCONN) { + /* + * If the connection is already disconnected + * we should return ECONNABORTED. + */ + saved_errno = ECONNABORTED; + } + errno = saved_errno; + return ret; + } + SWRAP_LOCK_SI(parent_si); ret = sockaddr_convert_from_un(parent_si, @@ -3663,8 +3682,10 @@ static int swrap_accept(int s, &in_addr.sa.s, &in_addr.sa_socklen); if (ret == -1) { + int saved_errno = errno; SWRAP_UNLOCK_SI(parent_si); libc_close(fd); + errno = saved_errno; return ret; } @@ -3692,14 +3713,6 @@ static int swrap_accept(int s, *addrlen = in_addr.sa_socklen; } - ret = libc_getsockname(fd, - &un_my_addr.sa.s, - &un_my_addr.sa_socklen); - if (ret == -1) { - libc_close(fd); - return ret; - } - ret = sockaddr_convert_from_un(child_si, &un_my_addr.sa.un, un_my_addr.sa_socklen, @@ -3707,7 +3720,9 @@ static int swrap_accept(int s, &in_my_addr.sa.s, &in_my_addr.sa_socklen); if (ret == -1) { + int saved_errno = errno; libc_close(fd); + errno = saved_errno; return ret; } -- cgit