diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index 8d8684602b..921f1ff696 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -932,6 +932,7 @@ struct isc_nmsocket { isc_tls_t *tls; isc_tlsctx_t *ctx; isc_nmsocket_t *tlslistener; + isc_nmsocket_t *tlssocket; atomic_bool result_updated; enum { TLS_INIT, diff --git a/lib/isc/netmgr/tlsstream.c b/lib/isc/netmgr/tlsstream.c index 252b52da9f..6ca7e03b59 100644 --- a/lib/isc/netmgr/tlsstream.c +++ b/lib/isc/netmgr/tlsstream.c @@ -200,7 +200,6 @@ tls_failed_read_cb(isc_nmsocket_t *sock, const isc_result_t result) { if (destroy) { isc__nmsocket_prep_destroy(sock); - isc__nmsocket_detach(&sock); } } @@ -401,21 +400,7 @@ tls_do_bio(isc_nmsocket_t *sock, isc_region_t *received_data, send_data->cb.send(send_data->handle, result, send_data->cbarg); send_data = NULL; - /* This situation might occur only when SSL - * shutdown was already sent (see - * tls_send_outgoing()), and we are in the - * process of shutting down the connection (in - * this case tls_senddone() will be called), but - * some code tries to send data over the - * connection and called isc_tls_send(). The - * socket will be detached there, in - * tls_senddone().*/ - if (sent_shutdown || received_shutdown) { - return; - } else { - isc__nmsocket_detach(&sock); - return; - } + return; } } @@ -614,6 +599,12 @@ tlslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) { tlssock->tlsstream.ctx = tlslistensock->tlsstream.ctx; + /* + * Hold a reference to tlssock in the TCP socket: it will + * detached in isc__nm_tls_cleanup_data(). + */ + handle->sock->tlsstream.tlssocket = tlssock; + result = initialize_tls(tlssock, true); RUNTIME_CHECK(result == ISC_R_SUCCESS); /* TODO: catch failure code, detach tlssock, and log the error */ @@ -814,7 +805,7 @@ tls_close_direct(isc_nmsocket_t *sock) { isc__nmsocket_detach(&sock->listener); } - /* further cleanup performed in isc__nm_tls_cleanup_data() */ + /* Further cleanup performed in isc__nm_tls_cleanup_data() */ atomic_store(&sock->closed, true); atomic_store(&sock->active, false); sock->tlsstream.state = TLS_CLOSED; @@ -939,6 +930,12 @@ tcp_connected(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) { isc_nmhandle_attach(handle, &tlssock->outerhandle); atomic_store(&tlssock->active, true); + /* + * Hold a reference to tlssock in the TCP socket: it will + * detached in isc__nm_tls_cleanup_data(). + */ + handle->sock->tlsstream.tlssocket = tlssock; + tls_do_bio(tlssock, NULL, NULL, false); return; error: @@ -1016,6 +1013,13 @@ isc__nm_tls_cleanup_data(isc_nmsocket_t *sock) { sock->tlsstream.bio_out = NULL; sock->tlsstream.bio_in = NULL; } + } else if (sock->type == isc_nm_tcpsocket && + sock->tlsstream.tlssocket != NULL) { + /* + * The TLS socket can't be destroyed until its underlying TCP + * socket is, to avoid possible use-after-free errors. + */ + isc__nmsocket_detach(&sock->tlsstream.tlssocket); } } -- 2.35.3