diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index c4265aa5c9..82c019168d 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -619,11 +619,10 @@ new_portentry(dns_dispatch_t *disp, in_port_t port) { } /*% - * The caller must not hold the qid->lock. + * The caller must hold the qid->lock. */ static void deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) { - dns_qid_t *qid; dispportentry_t *portentry = *portentryp; *portentryp = NULL; @@ -631,13 +630,10 @@ deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) { REQUIRE(portentry != NULL); if (isc_refcount_decrement(&portentry->refs) == 1) { - qid = DNS_QID(disp); - LOCK(&qid->lock); ISC_LIST_UNLINK(disp->port_table[portentry->port % DNS_DISPATCH_PORTTABLESIZE], portentry, link); isc_mempool_put(disp->portpool, portentry); - UNLOCK(&qid->lock); } } @@ -777,9 +773,9 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest, if (result == ISC_R_SUCCESS) { dispsock->socket = sock; dispsock->host = *dest; - dispsock->portentry = portentry; dispsock->bucket = bucket; LOCK(&qid->lock); + dispsock->portentry = portentry; ISC_LIST_APPEND(qid->sock_table[bucket], dispsock, blink); UNLOCK(&qid->lock); *dispsockp = dispsock; @@ -805,7 +801,7 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest, static void destroy_dispsocket(dns_dispatch_t *disp, dispsocket_t **dispsockp) { dispsocket_t *dispsock; - dns_qid_t *qid; + dns_qid_t *qid = DNS_QID(disp); /* * The dispatch must be locked. @@ -819,13 +815,15 @@ destroy_dispsocket(dns_dispatch_t *disp, dispsocket_t **dispsockp) { disp->nsockets--; dispsock->magic = 0; if (dispsock->portentry != NULL) { + /* socket_search() tests and dereferences portentry. */ + LOCK(&qid->lock); deref_portentry(disp, &dispsock->portentry); + UNLOCK(&qid->lock); } if (dispsock->socket != NULL) { isc_socket_detach(&dispsock->socket); } if (ISC_LINK_LINKED(dispsock, blink)) { - qid = DNS_QID(disp); LOCK(&qid->lock); ISC_LIST_UNLINK(qid->sock_table[dispsock->bucket], dispsock, blink); @@ -844,7 +842,7 @@ destroy_dispsocket(dns_dispatch_t *disp, dispsocket_t **dispsockp) { static void deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) { isc_result_t result; - dns_qid_t *qid; + dns_qid_t *qid = DNS_QID(disp); /* * The dispatch must be locked. @@ -856,14 +854,16 @@ deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) { } INSIST(dispsock->portentry != NULL); + /* socket_search() tests and dereferences portentry. */ + LOCK(&qid->lock); deref_portentry(disp, &dispsock->portentry); + UNLOCK(&qid->lock); if (disp->nsockets > DNS_DISPATCH_POOLSOCKS) { destroy_dispsocket(disp, &dispsock); } else { result = isc_socket_close(dispsock->socket); - qid = DNS_QID(disp); LOCK(&qid->lock); ISC_LIST_UNLINK(qid->sock_table[dispsock->bucket], dispsock, blink);