From 1967e2bdc468df2f91a20d5523719688a1287611 Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Mon, 14 Sep 2026 13:34:42 +0000 Subject: [PATCH] SSL: avoid writing to a connection with a failed read It is possible to receive application data together with socket close. In this case, SSL_read() may return SSL_ERROR_SYSCALL with ECONNRESET, specifically after OpenSSL sent TLSv1.3 tickets on a closed connection. Before OpenSSL 4.0, a subsequent SSL_write() returned SSL_ERROR_SYSCALL with EPIPE in this case. The behaviour was changed to remember the error state and handle such a call as a protocol error, see for details https://github.com/openssl/openssl/issues/30631. This makes SSL_write() return SSL_ERROR_SSL with the empty error queue, which results in "[crit] ... SSL_write() failed" errors, as caught by ssl_stapling.t. The fix is to check the result of the last read stored in c->ssl->last, to avoid calling SSL_write() after a failed read. For consistency, the check is added to ngx_ssl_sendfile(): SSL_sendfile() resets the error state the same way SSL_write() does, though it does not seem to be reachable in http. Based on a patch by Maxim Dounin. Signed-off-by: Sergey Kandaurov Origin: --- src/event/ngx_event_openssl.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index c9f94c982..c827b996f 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -3242,6 +3242,12 @@ ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size) int n, sslerr; ngx_err_t err; + if (c->ssl->last == NGX_ERROR) { + c->write->ready = 0; + c->write->error = 1; + return NGX_ERROR; + } + #ifdef SSL_READ_EARLY_DATA_SUCCESS if (c->ssl->in_early) { return ngx_ssl_write_early(c, data, size); @@ -3473,6 +3479,12 @@ ngx_ssl_sendfile(ngx_connection_t *c, ngx_buf_t *file, size_t size) ssize_t n; ngx_err_t err; + if (c->ssl->last == NGX_ERROR) { + c->write->ready = 0; + c->write->error = 1; + return NGX_ERROR; + } + ngx_ssl_clear_error(c->log); ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,