From e8b033871d015fffdabfd03a4fb1de2b9bf05a93 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Wed, 3 Dec 2008 02:21:48 +0000 Subject: [PATCH] 2504. [bug] Address race condition in the socket code. [RT #18899] --- CHANGES | 1 + lib/isc/unix/socket.c | 36 ++++++++++++++++++++++-------------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/CHANGES b/CHANGES index c7555ab38f8..0bbbd1a6912 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,4 @@ +2504. [bug] Address race condition in the socket code. [RT #18899] --- 9.6.0rc1 released --- diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c index 98d0ab6e749..0fdfe6586c2 100644 --- a/lib/isc/unix/socket.c +++ b/lib/isc/unix/socket.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: socket.c,v 1.308 2008/11/20 00:04:17 jinmei Exp $ */ +/* $Id: socket.c,v 1.308.12.1 2008/12/03 02:21:48 marka Exp $ */ /*! \file */ @@ -2360,18 +2360,15 @@ isc_socket_detach(isc_socket_t **socketp) { isc_result_t isc_socket_close(isc_socket_t *sock) { int fd; + isc_socketmgr_t *manager; + isc_sockettype_t type; REQUIRE(VALID_SOCKET(sock)); LOCK(&sock->lock); + REQUIRE(sock->references == 1); REQUIRE(sock->type != isc_sockettype_fdwatch); - UNLOCK(&sock->lock); - /* - * We don't need to retain the lock hereafter, since no one else has - * this socket. - */ - REQUIRE(sock->fd >= 0 && sock->fd < (int)sock->manager->maxsocks); INSIST(!sock->connecting); @@ -2383,6 +2380,8 @@ isc_socket_close(isc_socket_t *sock) { INSIST(ISC_LIST_EMPTY(sock->accept_list)); INSIST(sock->connect_ev == NULL); + manager = sock->manager; + type = sock->type; fd = sock->fd; sock->fd = -1; sock->listener = 0; @@ -2390,8 +2389,9 @@ isc_socket_close(isc_socket_t *sock) { sock->connecting = 0; sock->bound = 0; isc_sockaddr_any(&sock->peer_address); + UNLOCK(&sock->lock); - closesocket(sock->manager, sock->type, fd); + closesocket(manager, type, fd); return (ISC_R_SUCCESS); } @@ -3028,6 +3028,7 @@ process_fd(isc_socketmgr_t *manager, int fd, isc_boolean_t readable, { isc_socket_t *sock; isc_boolean_t unlock_sock; + isc_boolean_t unwatch_read = ISC_FALSE, unwatch_write = ISC_FALSE; int lockid = FDLOCK_ID(fd); /* @@ -3043,11 +3044,10 @@ process_fd(isc_socketmgr_t *manager, int fd, isc_boolean_t readable, } sock = manager->fds[fd]; - UNLOCK(&manager->fdlock[lockid]); unlock_sock = ISC_FALSE; if (readable) { if (sock == NULL) { - (void)unwatch_fd(manager, fd, SELECT_POKE_READ); + unwatch_read = ISC_TRUE; goto check_write; } unlock_sock = ISC_TRUE; @@ -3058,13 +3058,13 @@ process_fd(isc_socketmgr_t *manager, int fd, isc_boolean_t readable, else dispatch_recv(sock); } - (void)unwatch_fd(manager, fd, SELECT_POKE_READ); + unwatch_read = ISC_TRUE; } check_write: if (writeable) { if (sock == NULL) { - (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE); - return; + unwatch_write = ISC_TRUE; + goto unlock_fd; } if (!unlock_sock) { unlock_sock = ISC_TRUE; @@ -3076,10 +3076,18 @@ check_write: else dispatch_send(sock); } - (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE); + unwatch_write = ISC_TRUE; } if (unlock_sock) UNLOCK(&sock->lock); + + unlock_fd: + UNLOCK(&manager->fdlock[lockid]); + if (unwatch_read) + (void)unwatch_fd(manager, fd, SELECT_POKE_READ); + if (unwatch_write) + (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE); + } #ifdef USE_KQUEUE -- 2.47.3