Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 177 additions & 0 deletions SPECS/gnutls/CVE-2026-33845.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
From e5b72c53c7d789d19d1d1cd10b275e87d0415413 Mon Sep 17 00:00:00 2001
From: Alexander Sosedkin <asosedkin@redhat.com>
Date: Mon, 23 Mar 2026 15:09:43 +0100
Subject: [PATCH] buffers: switch from end_offset over to frag_length

Instead of maintaining an inclusive [start_offset, end_offset] range
when reassembling DTLS handshake,
track start_offset and a relative frag_length instead.

You would think it would be a no-op, but it fixes:

* 0-length fragments triggering completion if message was 1 byte long
* a remotely triggerable underflow and an ensuing heap overrun

Reported-by: Joshua Rogers of AISLE Research Team <joshua@joshua.hu>
Fixes: #1811
Fixes: CVE-2026-33845
Fixes: GNUTLS-SA-2026-04-29-3
CVSS: 7.5 High CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>

Upstream Patch Reference: https://gitlab.com/gnutls/gnutls/-/commit/e5b72c53c7d789d19d1d1cd10b275e87d0415413.patch
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
---
lib/buffers.c | 51 +++++++++++++++++++++++++-----------------------
lib/gnutls_int.h | 4 ++--
2 files changed, 29 insertions(+), 26 deletions(-)

diff --git a/lib/buffers.c b/lib/buffers.c
index e9ddf0403b..c3df8a37bc 100644
--- a/lib/buffers.c
+++ b/lib/buffers.c
@@ -923,10 +923,7 @@
}
data_size = _mbuffer_get_udata_size(bufel) - handshake_header_size;

- if (frag_size > 0)
- hsk->end_offset = hsk->start_offset + frag_size - 1;
- else
- hsk->end_offset = 0;
+ hsk->frag_length = frag_size;

_gnutls_handshake_log(
"HSK[%p]: %s (%u) was received. Length %d[%d], frag offset %d, frag length: %d, sequence: %d\n",
@@ -940,9 +937,11 @@

if (hsk->length > 0 &&
(frag_size > data_size ||
- (frag_size > 0 && hsk->end_offset >= hsk->length))) {
+ (frag_size > 0 &&
+ hsk->start_offset + frag_size > hsk->length))) {
return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
- } else if (hsk->length == 0 && hsk->end_offset != 0 &&
+ } else if (hsk->length == 0 &&
+ hsk->start_offset + frag_size != hsk->start_offset &&
hsk->start_offset != 0)
return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

@@ -991,11 +990,10 @@
hsk->data.length = hsk->length;
}

- if (hsk->length > 0 && hsk->end_offset > 0 &&
- hsk->end_offset - hsk->start_offset + 1 != hsk->length) {
+ if (hsk->length > 0 && hsk->frag_length > 0 &&
+ hsk->frag_length != hsk->length) {
memmove(&hsk->data.data[hsk->start_offset],
- hsk->data.data,
- hsk->end_offset - hsk->start_offset + 1);
+ hsk->data.data, hsk->frag_length);
}

session->internals.handshake_recv_buffer_size++;
@@ -1012,7 +1010,7 @@
if (hsk->start_offset <
session->internals.handshake_recv_buffer[pos]
.start_offset &&
- hsk->end_offset + 1 >=
+ hsk->start_offset + hsk->frag_length >=
session->internals.handshake_recv_buffer[pos]
.start_offset) {
memcpy(&session->internals.handshake_recv_buffer[pos]
@@ -1021,28 +1019,34 @@
session->internals.handshake_recv_buffer[pos]
.start_offset = hsk->start_offset;
session->internals.handshake_recv_buffer[pos]
- .end_offset = MIN(
- hsk->end_offset,
+ .frag_length = MIN(
+ hsk->frag_length,
session->internals.handshake_recv_buffer[pos]
- .end_offset);
- } else if (hsk->end_offset >
+ .frag_length);
+ } else if (hsk->start_offset + hsk->frag_length >
session->internals.handshake_recv_buffer[pos]
- .end_offset &&
+ .start_offset +
+ session->internals.handshake_recv_buffer[pos]
+ .frag_length &&
hsk->start_offset <=
session->internals.handshake_recv_buffer[pos]
- .end_offset +
- 1) {
+ .start_offset +
+ session->internals.handshake_recv_buffer[pos]
+ .frag_length) {
memcpy(&session->internals.handshake_recv_buffer[pos]
.data.data[hsk->start_offset],
hsk->data.data, hsk->data.length);

session->internals.handshake_recv_buffer[pos]
- .end_offset = hsk->end_offset;
- session->internals.handshake_recv_buffer[pos]
.start_offset = MIN(
hsk->start_offset,
session->internals.handshake_recv_buffer[pos]
.start_offset);
+ session->internals.handshake_recv_buffer[pos]
+ .frag_length = hsk->start_offset +
+ hsk->frag_length -
+ session->internals.handshake_recv_buffer[pos]
+ .start_offset;
}
_gnutls_handshake_buffer_clear(hsk);
}
@@ -1102,8 +1106,8 @@
}

else if ((recv_buf[LAST_ELEMENT].start_offset == 0 &&
- recv_buf[LAST_ELEMENT].end_offset ==
- recv_buf[LAST_ELEMENT].length - 1) ||
+ recv_buf[LAST_ELEMENT].frag_length ==
+ recv_buf[LAST_ELEMENT].length) ||
recv_buf[LAST_ELEMENT].length == 0) {
session->internals.dtls.hsk_read_seq++;
_gnutls_handshake_buffer_move(hsk,
@@ -1114,8 +1118,9 @@
/* if we don't have a complete handshake message, but we
* have queued data waiting, try again to reconstruct the
* handshake packet, using the queued */
- if (recv_buf[LAST_ELEMENT].end_offset !=
- recv_buf[LAST_ELEMENT].length - 1 &&
+ if ((recv_buf[LAST_ELEMENT].start_offset +
+ recv_buf[LAST_ELEMENT].frag_length) !=
+ recv_buf[LAST_ELEMENT].length &&
record_check_unprocessed(session) > 0)
return gnutls_assert_val(
GNUTLS_E_INT_CHECK_AGAIN);
@@ -1302,9 +1307,7 @@
&session->internals.record_buffer,
bufel, ret);

- data_size = MIN(tmp.length,
- tmp.end_offset -
- tmp.start_offset + 1);
+ data_size = MIN(tmp.length, tmp.frag_length);

ret = _gnutls_buffer_append_data(
&tmp.data,
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index d1643be9d4..3e5a8f3614 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -475,10 +475,10 @@
uint16_t sequence;

/* indicate whether that message is complete.
- * complete means start_offset == 0 and end_offset == length
+ * complete means start_offset == 0 and frag_length == length
*/
uint32_t start_offset;
- uint32_t end_offset;
+ uint32_t frag_length;

uint8_t header[MAX_HANDSHAKE_HEADER_SIZE];
int header_size;
6 changes: 5 additions & 1 deletion SPECS/gnutls/gnutls.spec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Summary: The GnuTLS Transport Layer Security Library
Name: gnutls
Version: 3.8.3
Release: 8%{?dist}
Release: 9%{?dist}
License: GPLv3+ AND LGPLv2.1+
Vendor: Microsoft Corporation
Distribution: Azure Linux
Expand All @@ -20,6 +20,7 @@ Patch7: CVE-2025-32988.patch
Patch8: CVE-2025-6395.patch
Patch9: CVE-2025-13151.patch
Patch10: CVE-2025-9820.patch
Patch11: CVE-2026-33845.patch
BuildRequires: autogen-libopts-devel
BuildRequires: gc-devel
BuildRequires: libtasn1-devel
Expand Down Expand Up @@ -101,6 +102,9 @@ sed -i 's/TESTS += test-ciphers-openssl.sh//' tests/slow/Makefile.am
%{_mandir}/man3/*

%changelog
* Thu May 07 2026 Akarsh Chaudhary <v-akarshc@microsoft.com>- 3.8.3-9
- Patch for CVE-2026-33845

* Wed Jan 28 2026 Akhila Guruju <v-guakhila@microsoft.com> - 3.8.3-8
- Patch CVE-2025-9820

Expand Down
Loading