From 5917c6780f2c7852fdcf08ae48fb3966acb34428 Mon Sep 17 00:00:00 2001 Message-ID: <5917c6780f2c7852fdcf08ae48fb3966acb34428.1754534163.git.sam@gentoo.org> From: Sam James Date: Thu, 7 Aug 2025 03:35:47 +0100 Subject: [PATCH] Revert "resolved: don't wait for TLS close_notify replies unnecessarily" Bug: https://github.com/systemd/systemd/issues/38509 This reverts commit 12a455db368340733ac9a701d9a5864b612d3408. --- a/src/resolve/resolved-dnstls-openssl.c +++ b/src/resolve/resolved-dnstls-openssl.c @@ -159,39 +159,42 @@ int dnstls_stream_on_io(DnsStream *stream, uint32_t revents) { } if (stream->dnstls_data.shutdown) { - /* NB: when a shutdown is initiated by us we'll wait until the close_notify TLS message is - * sent out, but we'll not wait for the reply to it, to minimize dependencies on slow - * servers */ - ERR_clear_error(); r = SSL_shutdown(stream->dnstls_data.ssl); - if (r < 0) { + if (r == 0) { + stream->dnstls_events = 0; + + r = dnstls_flush_write_buffer(stream); + if (r < 0) + return r; + + return -EAGAIN; + } else if (r < 0) { error = SSL_get_error(stream->dnstls_data.ssl, r); - if (error == SSL_ERROR_WANT_READ) - stream->dnstls_events = EPOLLIN; - else if (error == SSL_ERROR_WANT_WRITE) - stream->dnstls_events = EPOLLOUT; - else if (error == SSL_ERROR_SYSCALL) { - if (errno != 0) - log_debug_errno(errno, "Failed to invoke SSL_shutdown(), ignoring: %m"); - else - log_debug("Failed to invoke SSL_shutdown(), ignoring (unknown system error)."); + if (IN_SET(error, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE)) { + stream->dnstls_events = error == SSL_ERROR_WANT_READ ? EPOLLIN : EPOLLOUT; + + r = dnstls_flush_write_buffer(stream); + if (r < 0) + return r; + + return -EAGAIN; + } else if (error == SSL_ERROR_SYSCALL) { + if (errno > 0) + log_debug_errno(errno, "Failed to invoke SSL_shutdown, ignoring: %m"); } else - log_debug("Failed to invoke SSL_shutdown(), ignoring: %s", DNSTLS_ERROR_STRING(error)); - } else - stream->dnstls_events = 0; + log_debug("Failed to invoke SSL_shutdown, ignoring: %s", DNSTLS_ERROR_STRING(error)); + } + + stream->dnstls_events = 0; + stream->dnstls_data.shutdown = false; r = dnstls_flush_write_buffer(stream); if (r < 0) return r; - /* All data written? Then we are done, release the stream */ - - stream->dnstls_data.shutdown = false; dns_stream_unref(stream); - return DNSTLS_STREAM_CLOSED; - } else if (stream->dnstls_data.handshake <= 0) { ERR_clear_error(); stream->dnstls_data.handshake = SSL_do_handshake(stream->dnstls_data.ssl); @@ -238,35 +241,45 @@ int dnstls_stream_shutdown(DnsStream *stream, int error) { } if (error == ETIMEDOUT) { - /* Initiate a shutdown from our side, and remember so. Pin the stream until that's complete. */ - if (!stream->dnstls_data.shutdown) { - stream->dnstls_data.shutdown = true; - dns_stream_ref(stream); - } - ERR_clear_error(); r = SSL_shutdown(stream->dnstls_data.ssl); - if (r < 0) { + if (r == 0) { + if (!stream->dnstls_data.shutdown) { + stream->dnstls_data.shutdown = true; + dns_stream_ref(stream); + } + + stream->dnstls_events = 0; + + r = dnstls_flush_write_buffer(stream); + if (r < 0) + return r; + + return -EAGAIN; + } else if (r < 0) { ssl_error = SSL_get_error(stream->dnstls_data.ssl, r); - if (ssl_error == SSL_ERROR_WANT_READ) - stream->dnstls_events = EPOLLIN; - else if (ssl_error == SSL_ERROR_WANT_WRITE) - stream->dnstls_events = EPOLLOUT; - else if (ssl_error == SSL_ERROR_SYSCALL) { - if (errno != 0) - log_debug_errno(errno, "Failed to invoke SSL_shutdown(), ignoring: %m"); - else - log_debug("Failed to invoke SSL_shutdown(), ignoring (unknown system error)."); + if (IN_SET(ssl_error, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE)) { + stream->dnstls_events = ssl_error == SSL_ERROR_WANT_READ ? EPOLLIN : EPOLLOUT; + r = dnstls_flush_write_buffer(stream); + if (r < 0 && r != -EAGAIN) + return r; + + if (!stream->dnstls_data.shutdown) { + stream->dnstls_data.shutdown = true; + dns_stream_ref(stream); + } + return -EAGAIN; + } else if (ssl_error == SSL_ERROR_SYSCALL) { + if (errno > 0) + log_debug_errno(errno, "Failed to invoke SSL_shutdown, ignoring: %m"); } else - log_debug("Failed to invoke SSL_shutdown(), ignoring: %s", DNSTLS_ERROR_STRING(error)); - } else - stream->dnstls_events = 0; + log_debug("Failed to invoke SSL_shutdown, ignoring: %s", DNSTLS_ERROR_STRING(ssl_error)); + } + stream->dnstls_events = 0; r = dnstls_flush_write_buffer(stream); if (r < 0) return r; - - /* dnstls_stream_on_io() will complete the shutdown for us */ } return 0; -- 2.50.1