summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2021-02-05 12:13:12 +0100
committerAndreas Schneider <asn@samba.org>2021-02-05 14:11:31 +0100
commite72898ad92a52a595d4733210483e9689cb5d390 (patch)
treee99fc74e8168dd246f3ae2dd0c5195d4967c4c9e /src
parentc3f7465f9cf453ff3bd53750db4024deaba02fb5 (diff)
downloadsocket_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.c33
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;
}