diff options
| author | Stefan Metzmacher <metze@samba.org> | 2021-02-05 12:13:12 +0100 |
|---|---|---|
| committer | Andreas Schneider <asn@samba.org> | 2021-02-05 14:11:31 +0100 |
| commit | e72898ad92a52a595d4733210483e9689cb5d390 (patch) | |
| tree | e99fc74e8168dd246f3ae2dd0c5195d4967c4c9e /src | |
| parent | c3f7465f9cf453ff3bd53750db4024deaba02fb5 (diff) | |
| download | socket_wrapper-e72898ad92a52a595d4733210483e9689cb5d390.tar.gz socket_wrapper-e72898ad92a52a595d4733210483e9689cb5d390.tar.xz socket_wrapper-e72898ad92a52a595d4733210483e9689cb5d390.zip | |
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 <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
Diffstat (limited to 'src')
| -rw-r--r-- | src/socket_wrapper.c | 33 |
1 files changed, 24 insertions, 9 deletions
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; } |
