2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 14:35:26 +00:00

2504. [bug] Address race condition in the socket code. [RT #18899]

This commit is contained in:
Mark Andrews
2008-12-03 02:03:47 +00:00
parent fc8e82904a
commit d8fc8514b1
2 changed files with 25 additions and 15 deletions

View File

@@ -1,3 +1,5 @@
2504. [bug] Address race condition in the socket code. [RT #18899]
2503. [port] linux: improve compatibility with Linux Standard 2503. [port] linux: improve compatibility with Linux Standard
Base. [RT #18793] Base. [RT #18793]

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: socket.c,v 1.309 2008/12/01 00:15:37 marka Exp $ */ /* $Id: socket.c,v 1.310 2008/12/03 02:03:47 marka Exp $ */
/*! \file */ /*! \file */
@@ -2360,18 +2360,15 @@ isc_socket_detach(isc_socket_t **socketp) {
isc_result_t isc_result_t
isc_socket_close(isc_socket_t *sock) { isc_socket_close(isc_socket_t *sock) {
int fd; int fd;
isc_socketmgr_t *manager;
isc_sockettype_t type;
REQUIRE(VALID_SOCKET(sock)); REQUIRE(VALID_SOCKET(sock));
LOCK(&sock->lock); LOCK(&sock->lock);
REQUIRE(sock->references == 1); REQUIRE(sock->references == 1);
REQUIRE(sock->type != isc_sockettype_fdwatch); 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); REQUIRE(sock->fd >= 0 && sock->fd < (int)sock->manager->maxsocks);
INSIST(!sock->connecting); INSIST(!sock->connecting);
@@ -2383,6 +2380,8 @@ isc_socket_close(isc_socket_t *sock) {
INSIST(ISC_LIST_EMPTY(sock->accept_list)); INSIST(ISC_LIST_EMPTY(sock->accept_list));
INSIST(sock->connect_ev == NULL); INSIST(sock->connect_ev == NULL);
manager = sock->manager;
type = sock->type;
fd = sock->fd; fd = sock->fd;
sock->fd = -1; sock->fd = -1;
sock->listener = 0; sock->listener = 0;
@@ -2390,8 +2389,9 @@ isc_socket_close(isc_socket_t *sock) {
sock->connecting = 0; sock->connecting = 0;
sock->bound = 0; sock->bound = 0;
isc_sockaddr_any(&sock->peer_address); isc_sockaddr_any(&sock->peer_address);
UNLOCK(&sock->lock);
closesocket(sock->manager, sock->type, fd); closesocket(manager, type, fd);
return (ISC_R_SUCCESS); 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_socket_t *sock;
isc_boolean_t unlock_sock; isc_boolean_t unlock_sock;
isc_boolean_t unwatch_read = ISC_FALSE, unwatch_write = ISC_FALSE;
int lockid = FDLOCK_ID(fd); int lockid = FDLOCK_ID(fd);
/* /*
@@ -3043,28 +3044,27 @@ process_fd(isc_socketmgr_t *manager, int fd, isc_boolean_t readable,
} }
sock = manager->fds[fd]; sock = manager->fds[fd];
UNLOCK(&manager->fdlock[lockid]);
unlock_sock = ISC_FALSE; unlock_sock = ISC_FALSE;
if (readable) { if (readable) {
if (sock == NULL) { if (sock == NULL) {
(void)unwatch_fd(manager, fd, SELECT_POKE_READ); unwatch_read = ISC_TRUE;
goto check_write; goto check_write;
} }
unlock_sock = ISC_TRUE; unlock_sock = ISC_TRUE;
LOCK(&sock->lock); LOCK(&sock->lock); /* XXXMPA */
if (!SOCK_DEAD(sock)) { if (!SOCK_DEAD(sock)) {
if (sock->listener) if (sock->listener)
dispatch_accept(sock); dispatch_accept(sock);
else else
dispatch_recv(sock); dispatch_recv(sock);
} }
(void)unwatch_fd(manager, fd, SELECT_POKE_READ); unwatch_read = ISC_TRUE;
} }
check_write: check_write:
if (writeable) { if (writeable) {
if (sock == NULL) { if (sock == NULL) {
(void)unwatch_fd(manager, fd, SELECT_POKE_WRITE); unwatch_write = ISC_TRUE;
return; goto unlock_fd;
} }
if (!unlock_sock) { if (!unlock_sock) {
unlock_sock = ISC_TRUE; unlock_sock = ISC_TRUE;
@@ -3076,10 +3076,18 @@ check_write:
else else
dispatch_send(sock); dispatch_send(sock);
} }
(void)unwatch_fd(manager, fd, SELECT_POKE_WRITE); unwatch_write = ISC_TRUE;
} }
if (unlock_sock) if (unlock_sock)
UNLOCK(&sock->lock); 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 #ifdef USE_KQUEUE