git: 7b8e59ccbdfc - stable/14 - openssl: Fix CVE-2026-84782

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Tue, 29 Sep 2026 15:56:42 UTC
The branch stable/14 has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=7b8e59ccbdfc91acbb1b648a1765e452304606b9

commit 7b8e59ccbdfc91acbb1b648a1765e452304606b9
Author:     Gordon Tetlow <gordon@FreeBSD.org>
AuthorDate: 2026-09-27 22:05:27 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-09-29 15:56:33 +0000

    openssl: Fix CVE-2026-84782
    
    This is a backport of an upstream commit to fix:
      dtls: reset init_off before retransmitting a message
    
    Approved by:    so
    Security:       FreeBSD-SA-26:68.openssl
    Security:       CVE-2026-84782
---
 crypto/openssl/ssl/d1_lib.c             | 17 +++++++++++++++++
 crypto/openssl/ssl/statem/statem_dtls.c |  2 ++
 2 files changed, 19 insertions(+)

diff --git a/crypto/openssl/ssl/d1_lib.c b/crypto/openssl/ssl/d1_lib.c
index 3b4328d3c35a..d954b40a94eb 100644
--- a/crypto/openssl/ssl/d1_lib.c
+++ b/crypto/openssl/ssl/d1_lib.c
@@ -416,6 +416,23 @@ int dtls1_handle_timeout(SSL *s)
     }
 
     dtls1_start_timer(s);
+
+    /*
+     * If write_state is anything other than WRITE_STATE_TRANSITION, a write
+     * is still parked mid-flight (WANT_WRITE) from a previous call into the
+     * state machine - the current flight hasn't actually finished going out
+     * yet, so there's nothing valid to retransmit. Retransmitting anyway
+     * would reconstruct an already-sent message from the retransmit queue
+     * into s->init_buf/s->init_off/s->init_num/s->d1->w_msg - the same
+     * fields the parked write is still using - corrupting that write's
+     * state out from under it. Leave it alone and let the next
+     * SSL_read()/SSL_write()/SSL_accept()/SSL_connect() call resume the
+     * parked write normally instead.
+     */
+    if (s->statem.state == MSG_FLOW_WRITING
+        && s->statem.write_state != WRITE_STATE_TRANSITION)
+        return 0;
+
     /* Calls SSLfatal() if required */
     return dtls1_retransmit_buffered_messages(s);
 }
diff --git a/crypto/openssl/ssl/statem/statem_dtls.c b/crypto/openssl/ssl/statem/statem_dtls.c
index ec6dee45b5d5..668b838b6600 100644
--- a/crypto/openssl/ssl/statem/statem_dtls.c
+++ b/crypto/openssl/ssl/statem/statem_dtls.c
@@ -1196,6 +1196,8 @@ int dtls1_retransmit_message(SSL *s, unsigned short seq, int *found)
     memcpy(s->init_buf->data, frag->fragment,
         frag->msg_header.msg_len + header_length);
     s->init_num = frag->msg_header.msg_len + header_length;
+    /* Always retransmit from the start, not wherever init_off was left */
+    s->init_off = 0;
 
     dtls1_set_message_header_int(s, frag->msg_header.type,
         frag->msg_header.msg_len,