2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-23 18:49:54 +00:00

Merge branch '3400-gracefully-handle-the-errors-from-uv_start_read' into 'main'

Gracefully handle uv_read_start() failures

Closes #3400

See merge request isc-projects/bind9!6424
This commit is contained in:
Ondřej Surý 2022-06-14 09:46:54 +00:00
commit e8cc03f1df
8 changed files with 81 additions and 30 deletions

View File

@ -1,3 +1,8 @@
5905. [bug] When the TCP connection would be closed/reset between
the connect/accept and the read, the uv_read_start()
return value would be unexpected and cause an assertion
failure. [GL #3400]
5904. [func] Changed dnssec-signzone -H default to 0 additional 5904. [func] Changed dnssec-signzone -H default to 0 additional
NSEC3 iterations. [GL #3395] NSEC3 iterations. [GL #3395]

View File

@ -46,3 +46,6 @@ Bug Fixes
- It was possible for a catalog zone consumer to process a catalog zone member - It was possible for a catalog zone consumer to process a catalog zone member
zone when there was a configured pre-existing forward-only forward zone with zone when there was a configured pre-existing forward-only forward zone with
the same name. This has been fixed. :gl:`#2506`. the same name. This has been fixed. :gl:`#2506`.
- Fix the assertion failure caused by TCP connection closing between the
connect (or accept) and the read from the socket. :gl:`#3400`

View File

@ -2098,11 +2098,11 @@ isc__nm_tcpdns_read_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf);
void void
isc__nm_tlsdns_read_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); isc__nm_tlsdns_read_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf);
void isc_result_t
isc__nm_start_reading(isc_nmsocket_t *sock); isc__nm_start_reading(isc_nmsocket_t *sock);
void void
isc__nm_stop_reading(isc_nmsocket_t *sock); isc__nm_stop_reading(isc_nmsocket_t *sock);
void isc_result_t
isc__nm_process_sock_buffer(isc_nmsocket_t *sock); isc__nm_process_sock_buffer(isc_nmsocket_t *sock);
void void
isc__nm_resume_processing(void *arg); isc__nm_resume_processing(void *arg);

View File

@ -2161,39 +2161,42 @@ isc__nm_alloc_cb(uv_handle_t *handle, size_t size, uv_buf_t *buf) {
worker->recvbuf_inuse = true; worker->recvbuf_inuse = true;
} }
void isc_result_t
isc__nm_start_reading(isc_nmsocket_t *sock) { isc__nm_start_reading(isc_nmsocket_t *sock) {
isc_result_t result = ISC_R_SUCCESS;
int r; int r;
if (atomic_load(&sock->reading)) { if (atomic_load(&sock->reading)) {
return; return (ISC_R_SUCCESS);
} }
switch (sock->type) { switch (sock->type) {
case isc_nm_udpsocket: case isc_nm_udpsocket:
r = uv_udp_recv_start(&sock->uv_handle.udp, isc__nm_alloc_cb, r = uv_udp_recv_start(&sock->uv_handle.udp, isc__nm_alloc_cb,
isc__nm_udp_read_cb); isc__nm_udp_read_cb);
UV_RUNTIME_CHECK(uv_udp_recv_start, r);
break; break;
case isc_nm_tcpsocket: case isc_nm_tcpsocket:
r = uv_read_start(&sock->uv_handle.stream, isc__nm_alloc_cb, r = uv_read_start(&sock->uv_handle.stream, isc__nm_alloc_cb,
isc__nm_tcp_read_cb); isc__nm_tcp_read_cb);
UV_RUNTIME_CHECK(uv_read_start, r);
break; break;
case isc_nm_tcpdnssocket: case isc_nm_tcpdnssocket:
r = uv_read_start(&sock->uv_handle.stream, isc__nm_alloc_cb, r = uv_read_start(&sock->uv_handle.stream, isc__nm_alloc_cb,
isc__nm_tcpdns_read_cb); isc__nm_tcpdns_read_cb);
UV_RUNTIME_CHECK(uv_read_start, r);
break; break;
case isc_nm_tlsdnssocket: case isc_nm_tlsdnssocket:
r = uv_read_start(&sock->uv_handle.stream, isc__nm_alloc_cb, r = uv_read_start(&sock->uv_handle.stream, isc__nm_alloc_cb,
isc__nm_tlsdns_read_cb); isc__nm_tlsdns_read_cb);
UV_RUNTIME_CHECK(uv_read_start, r);
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
atomic_store(&sock->reading, true); if (r != 0) {
result = isc_uverr2result(r);
} else {
atomic_store(&sock->reading, true);
}
return (result);
} }
void void
@ -2254,7 +2257,7 @@ processbuffer(isc_nmsocket_t *sock) {
* Stop reading if this is a client socket. In this case we'll be * Stop reading if this is a client socket. In this case we'll be
* called again later by isc__nm_resume_processing(). * called again later by isc__nm_resume_processing().
*/ */
void isc_result_t
isc__nm_process_sock_buffer(isc_nmsocket_t *sock) { isc__nm_process_sock_buffer(isc_nmsocket_t *sock) {
for (;;) { for (;;) {
int_fast32_t ah = atomic_load(&sock->ah); int_fast32_t ah = atomic_load(&sock->ah);
@ -2265,7 +2268,10 @@ isc__nm_process_sock_buffer(isc_nmsocket_t *sock) {
* Don't reset the timer until we have a * Don't reset the timer until we have a
* full DNS message. * full DNS message.
*/ */
isc__nm_start_reading(sock); result = isc__nm_start_reading(sock);
if (result != ISC_R_SUCCESS) {
return (result);
}
/* /*
* Start the timer only if there are no externally used * Start the timer only if there are no externally used
* active handles, there's always one active handle * active handles, there's always one active handle
@ -2275,11 +2281,11 @@ isc__nm_process_sock_buffer(isc_nmsocket_t *sock) {
if (ah == 1) { if (ah == 1) {
isc__nmsocket_timer_start(sock); isc__nmsocket_timer_start(sock);
} }
return; goto done;
case ISC_R_CANCELED: case ISC_R_CANCELED:
isc__nmsocket_timer_stop(sock); isc__nmsocket_timer_stop(sock);
isc__nm_stop_reading(sock); isc__nm_stop_reading(sock);
return; goto done;
case ISC_R_SUCCESS: case ISC_R_SUCCESS:
/* /*
* Stop the timer on the successful message read, this * Stop the timer on the successful message read, this
@ -2290,13 +2296,15 @@ isc__nm_process_sock_buffer(isc_nmsocket_t *sock) {
if (atomic_load(&sock->client)) { if (atomic_load(&sock->client)) {
isc__nm_stop_reading(sock); isc__nm_stop_reading(sock);
return; goto done;
} }
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
} }
done:
return (ISC_R_SUCCESS);
} }
void void

View File

@ -747,18 +747,24 @@ isc__nm_async_tcpstartread(isc__networker_t *worker, isc__netievent_t *ev0) {
isc__netievent_tcpstartread_t *ievent = isc__netievent_tcpstartread_t *ievent =
(isc__netievent_tcpstartread_t *)ev0; (isc__netievent_tcpstartread_t *)ev0;
isc_nmsocket_t *sock = ievent->sock; isc_nmsocket_t *sock = ievent->sock;
isc_result_t result;
REQUIRE(VALID_NMSOCK(sock)); REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid()); REQUIRE(sock->tid == isc_nm_tid());
UNUSED(worker); UNUSED(worker);
if (isc__nmsocket_closing(sock)) { if (isc__nmsocket_closing(sock)) {
result = ISC_R_CANCELED;
} else {
result = isc__nm_start_reading(sock);
}
if (result != ISC_R_SUCCESS) {
atomic_store(&sock->reading, true); atomic_store(&sock->reading, true);
isc__nm_tcp_failed_read_cb(sock, ISC_R_CANCELED); isc__nm_tcp_failed_read_cb(sock, result);
return; return;
} }
isc__nm_start_reading(sock);
isc__nmsocket_timer_start(sock); isc__nmsocket_timer_start(sock);
} }

View File

@ -714,6 +714,7 @@ isc__nm_async_tcpdnsread(isc__networker_t *worker, isc__netievent_t *ev0) {
isc__netievent_tcpdnsread_t *ievent = isc__netievent_tcpdnsread_t *ievent =
(isc__netievent_tcpdnsread_t *)ev0; (isc__netievent_tcpdnsread_t *)ev0;
isc_nmsocket_t *sock = ievent->sock; isc_nmsocket_t *sock = ievent->sock;
isc_result_t result;
UNUSED(worker); UNUSED(worker);
@ -721,12 +722,15 @@ isc__nm_async_tcpdnsread(isc__networker_t *worker, isc__netievent_t *ev0) {
REQUIRE(sock->tid == isc_nm_tid()); REQUIRE(sock->tid == isc_nm_tid());
if (isc__nmsocket_closing(sock)) { if (isc__nmsocket_closing(sock)) {
atomic_store(&sock->reading, true); result = ISC_R_CANCELED;
isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false); } else {
return; result = isc__nm_process_sock_buffer(sock);
} }
isc__nm_process_sock_buffer(sock); if (result != ISC_R_SUCCESS) {
atomic_store(&sock->reading, true);
isc__nm_failed_read_cb(sock, result, false);
}
} }
/* /*
@ -836,6 +840,7 @@ isc__nm_tcpdns_read_cb(uv_stream_t *stream, ssize_t nread,
isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)stream); isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)stream);
uint8_t *base = NULL; uint8_t *base = NULL;
size_t len; size_t len;
isc_result_t result;
REQUIRE(VALID_NMSOCK(sock)); REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid()); REQUIRE(sock->tid == isc_nm_tid());
@ -878,7 +883,10 @@ isc__nm_tcpdns_read_cb(uv_stream_t *stream, ssize_t nread,
sock->read_timeout = atomic_load(&sock->mgr->idle); sock->read_timeout = atomic_load(&sock->mgr->idle);
} }
isc__nm_process_sock_buffer(sock); result = isc__nm_process_sock_buffer(sock);
if (result != ISC_R_SUCCESS) {
isc__nm_failed_read_cb(sock, result, true);
}
free: free:
if (nread < 0) { if (nread < 0) {
/* /*
@ -1029,7 +1037,12 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) {
* prep_destroy()->tcpdns_close_direct(). * prep_destroy()->tcpdns_close_direct().
*/ */
isc_nmhandle_attach(handle, &csock->recv_handle); isc_nmhandle_attach(handle, &csock->recv_handle);
isc__nm_process_sock_buffer(csock); result = isc__nm_process_sock_buffer(csock);
if (result != ISC_R_SUCCESS) {
isc_nmhandle_detach(&csock->recv_handle);
isc_nmhandle_detach(&handle);
goto failure;
}
/* /*
* The initial timer has been set, update the read timeout for the next * The initial timer has been set, update the read timeout for the next

View File

@ -316,7 +316,11 @@ tlsdns_connect_cb(uv_connect_t *uvreq, int status) {
/* Setting pending req */ /* Setting pending req */
sock->tls.pending_req = req; sock->tls.pending_req = req;
isc__nm_process_sock_buffer(sock); result = isc__nm_process_sock_buffer(sock);
if (result != ISC_R_SUCCESS) {
sock->tls.pending_req = NULL;
goto error;
}
result = tls_cycle(sock); result = tls_cycle(sock);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
@ -1068,8 +1072,10 @@ tls_cycle_input(isc_nmsocket_t *sock) {
/* /*
* Process what's in the buffer so far * Process what's in the buffer so far
*/ */
isc__nm_process_sock_buffer(sock); result = isc__nm_process_sock_buffer(sock);
if (result != ISC_R_SUCCESS) {
goto failure;
}
/* /*
* FIXME: Should we call * FIXME: Should we call
* isc__nm_failed_read_cb()? * isc__nm_failed_read_cb()?
@ -1081,7 +1087,10 @@ tls_cycle_input(isc_nmsocket_t *sock) {
sock->buf_len += len; sock->buf_len += len;
isc__nm_process_sock_buffer(sock); result = isc__nm_process_sock_buffer(sock);
if (result != ISC_R_SUCCESS) {
goto failure;
}
} }
} else if (!SSL_is_init_finished(sock->tls.tls)) { } else if (!SSL_is_init_finished(sock->tls.tls)) {
if (SSL_is_server(sock->tls.tls)) { if (SSL_is_server(sock->tls.tls)) {
@ -1103,7 +1112,10 @@ tls_cycle_input(isc_nmsocket_t *sock) {
if (sock->tls.state == TLS_STATE_NONE && if (sock->tls.state == TLS_STATE_NONE &&
!SSL_is_init_finished(sock->tls.tls)) { !SSL_is_init_finished(sock->tls.tls)) {
sock->tls.state = TLS_STATE_HANDSHAKE; sock->tls.state = TLS_STATE_HANDSHAKE;
isc__nm_process_sock_buffer(sock); result = isc__nm_process_sock_buffer(sock);
if (result != ISC_R_SUCCESS) {
goto failure;
}
} }
/* else continue reading */ /* else continue reading */
break; break;
@ -1656,7 +1668,10 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) {
isc_nmhandle_detach(&handle); isc_nmhandle_detach(&handle);
isc__nm_process_sock_buffer(csock); result = isc__nm_process_sock_buffer(csock);
if (result != ISC_R_SUCCESS) {
goto failure;
}
/* /*
* sock is now attached to the handle. * sock is now attached to the handle.

View File

@ -1118,7 +1118,7 @@ void
isc__nm_async_udpread(isc__networker_t *worker, isc__netievent_t *ev0) { isc__nm_async_udpread(isc__networker_t *worker, isc__netievent_t *ev0) {
isc__netievent_udpread_t *ievent = (isc__netievent_udpread_t *)ev0; isc__netievent_udpread_t *ievent = (isc__netievent_udpread_t *)ev0;
isc_nmsocket_t *sock = ievent->sock; isc_nmsocket_t *sock = ievent->sock;
isc_result_t result = ISC_R_SUCCESS; isc_result_t result;
UNUSED(worker); UNUSED(worker);
@ -1129,6 +1129,8 @@ isc__nm_async_udpread(isc__networker_t *worker, isc__netievent_t *ev0) {
result = ISC_R_SHUTTINGDOWN; result = ISC_R_SHUTTINGDOWN;
} else if (isc__nmsocket_closing(sock)) { } else if (isc__nmsocket_closing(sock)) {
result = ISC_R_CANCELED; result = ISC_R_CANCELED;
} else {
result = isc__nm_start_reading(sock);
} }
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
@ -1137,7 +1139,6 @@ isc__nm_async_udpread(isc__networker_t *worker, isc__netievent_t *ev0) {
return; return;
} }
isc__nm_start_reading(sock);
isc__nmsocket_timer_start(sock); isc__nmsocket_timer_start(sock);
} }