Openembedded Core Discussions
 help / color / mirror / Atom feed
* [OE-core][wrynose][PATCH] gnutls: fix CVE-2026-33845
@ 2026-07-27 15:33 Adarsh Jagadish Kamini
  2026-08-24 15:29 ` Yoann Congal
  0 siblings, 1 reply; 3+ messages in thread
From: Adarsh Jagadish Kamini @ 2026-07-27 15:33 UTC (permalink / raw)
  To: openembedded-core

Backport patch to fix CVE-2026-33845.

References:
  https://nvd.nist.gov/vuln/detail/CVE-2026-33845

Upstream fix:
  https://gitlab.com/gnutls/gnutls/-/commit/e5b72c53c7d789d19d1d1cd10b275e87d0415413

Tested with ptest:
Before: PASSED: 371, FAILED: 0, SKIPPED: 15
After: PASSED: 371, FAILED: 0, SKIPPED: 15

Signed-off-by: Adarsh Jagadish Kamini <adarsh.jagadish.kamini@est.tech>
---
 .../gnutls/gnutls/CVE-2026-33845.patch        | 195 ++++++++++++++++++
 meta/recipes-support/gnutls/gnutls_3.8.12.bb  |   1 +
 2 files changed, 196 insertions(+)
 create mode 100644 meta/recipes-support/gnutls/gnutls/CVE-2026-33845.patch

diff --git a/meta/recipes-support/gnutls/gnutls/CVE-2026-33845.patch b/meta/recipes-support/gnutls/gnutls/CVE-2026-33845.patch
new file mode 100644
index 0000000000..d81ffb7ef7
--- /dev/null
+++ b/meta/recipes-support/gnutls/gnutls/CVE-2026-33845.patch
@@ -0,0 +1,195 @@
+From 9679a9c8ab1694b78c7cb285d29da904e3f3bc45 Mon Sep 17 00:00:00 2001
+From: Adarsh Jagadish Kamini <adarsh.jagadish.kamini@est.tech>
+Date: Mon, 27 Jul 2026 08:58:02 +0000
+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'd think it'd 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>
+
+CVE: CVE-2026-33845
+Upstream-Status: Backport [https://gitlab.com/gnutls/gnutls/-/commit/e5b72c53c7d789d19d1d1cd10b275e87d0415413]
+
+Backport notes: adapted to the stable branch, no logic changes.
+- lib/buffers.c: the local fragment-size variable is named frag_size here,
+  not frag_length as upstream; renamed accordingly.
+- lib/buffers.c: merge_handshake_packet() has no recv_buf alias in this
+  branch, so recv_buf[pos] was expanded to
+  session->internals.handshake_recv_buffer[pos], which changes line wrapping.
+- lib/gnutls_int.h: applies cleanly.
+
+Assisted-by: kiro:claude-sonnet-4.6
+Signed-off-by: Adarsh Jagadish Kamini <adarsh.jagadish.kamini@est.tech>
+---
+ lib/buffers.c    | 57 ++++++++++++++++++++++++------------------------
+ lib/gnutls_int.h |  4 ++--
+ 2 files changed, 31 insertions(+), 30 deletions(-)
+
+diff --git a/lib/buffers.c b/lib/buffers.c
+index 672380b05..2d77e7590 100644
+--- a/lib/buffers.c
++++ b/lib/buffers.c
+@@ -923,10 +923,7 @@ static int parse_handshake_header(gnutls_session_t session, mbuffer_st *bufel,
+ 	}
+ 	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,10 @@ static int parse_handshake_header(gnutls_session_t session, mbuffer_st *bufel,
+ 
+ 	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 +989,10 @@ static int merge_handshake_packet(gnutls_session_t session,
+ 			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 +1009,7 @@ static int merge_handshake_packet(gnutls_session_t session,
+ 		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 +1018,34 @@ static int merge_handshake_packet(gnutls_session_t session,
+ 			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]
++					   .start_offset +
+ 				   session->internals.handshake_recv_buffer[pos]
+-					   .end_offset &&
++					   .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 +1105,8 @@ static int get_last_packet(gnutls_session_t session,
+ 		}
+ 
+ 		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 +1117,9 @@ static int get_last_packet(gnutls_session_t session,
+ 			/* 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 +1306,7 @@ int _gnutls_parse_record_buffered_msgs(gnutls_session_t session)
+ 					&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,
+@@ -1320,7 +1322,6 @@ int _gnutls_parse_record_buffered_msgs(gnutls_session_t session)
+ 				ret = merge_handshake_packet(session, &tmp);
+ 				if (ret < 0)
+ 					return gnutls_assert_val(ret);
+-
+ 			} while (_mbuffer_get_udata_size(bufel) > 0);
+ 
+ 			prev = bufel;
+diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
+index 54d3c9f67..283f25c07 100644
+--- a/lib/gnutls_int.h
++++ b/lib/gnutls_int.h
+@@ -479,10 +479,10 @@ typedef struct {
+ 	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; /* used exclusively in DTLS reassembly */
+ 
+ 	uint8_t header[MAX_HANDSHAKE_HEADER_SIZE];
+ 	int header_size;
diff --git a/meta/recipes-support/gnutls/gnutls_3.8.12.bb b/meta/recipes-support/gnutls/gnutls_3.8.12.bb
index 468b4bdd40..4219a650de 100644
--- a/meta/recipes-support/gnutls/gnutls_3.8.12.bb
+++ b/meta/recipes-support/gnutls/gnutls_3.8.12.bb
@@ -25,6 +25,7 @@ SRC_URI = "https://www.gnupg.org/ftp/gcrypt/gnutls/v${SHRT_VER}/gnutls-${PV}.tar
            file://Add-ptest-support.patch \
            file://c99.patch \
            file://CVE-2026-3833.patch \
+           file://CVE-2026-33845.patch \
            "
 
 SRC_URI[sha256sum] = "a7b341421bfd459acf7a374ca4af3b9e06608dcd7bd792b2bf470bea012b8e51"


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [OE-core][wrynose][PATCH] gnutls: fix CVE-2026-33845
  2026-07-27 15:33 [OE-core][wrynose][PATCH] gnutls: fix CVE-2026-33845 Adarsh Jagadish Kamini
@ 2026-08-24 15:29 ` Yoann Congal
  2026-08-25  8:02   ` Adarsh Jagadish Kamini
  0 siblings, 1 reply; 3+ messages in thread
From: Yoann Congal @ 2026-08-24 15:29 UTC (permalink / raw)
  To: adarsh.jagadish.kamini, openembedded-core

On Mon Jul 27, 2026 at 5:33 PM CEST, Adarsh Jagadish Kamini via lists.openembedded.org wrote:
> Backport patch to fix CVE-2026-33845.
>
> References:
>   https://nvd.nist.gov/vuln/detail/CVE-2026-33845
>
> Upstream fix:
>   https://gitlab.com/gnutls/gnutls/-/commit/e5b72c53c7d789d19d1d1cd10b275e87d0415413
>
> Tested with ptest:
> Before: PASSED: 371, FAILED: 0, SKIPPED: 15
> After: PASSED: 371, FAILED: 0, SKIPPED: 15
>
> Signed-off-by: Adarsh Jagadish Kamini <adarsh.jagadish.kamini@est.tech>
> ---
>  .../gnutls/gnutls/CVE-2026-33845.patch        | 195 ++++++++++++++++++
>  meta/recipes-support/gnutls/gnutls_3.8.12.bb  |   1 +
>  2 files changed, 196 insertions(+)
>  create mode 100644 meta/recipes-support/gnutls/gnutls/CVE-2026-33845.patch

Hello,

It looks like this patch does not apply to wrynose anymore:
| ERROR: gnutls-3.8.12-r0 do_patch: Applying patch '.../wrynose/bitbake-builds/poky-wrynose/layers/openembedded-core/meta/recipes-support/gnutls/gnutls/CVE-2026-33845.patch' on target directory '.../wrynose/bitbake-builds/poky-wrynose/build/tmp/work/x86-64-v3-poky-linux/gnutls/3.8.12/sources/gnutls-3.8.12'
| CmdError('quilt --quiltrc .../wrynose/bitbake-builds/poky-wrynose/build/tmp/work/x86-64-v3-poky-linux/gnutls/3.8.12/recipe-sysroot-native/etc/quiltrc push', 0, 'stdout: Applying patch CVE-2026-33845.patch
| patching file lib/buffers.c
| Hunk #1 succeeded at 919 (offset -4 lines).
| Hunk #2 succeeded at 933 (offset -4 lines).
| Hunk #3 succeeded at 1000 (offset 11 lines).
| Hunk #4 FAILED at 1009.
| Hunk #5 FAILED at 1018.
| Hunk #6 succeeded at 1110 (offset 11 lines).
| Hunk #7 succeeded at 1122 (offset 11 lines).
| Hunk #8 succeeded at 1311 (offset 11 lines).
| Hunk #9 succeeded at 1327 (offset 11 lines).
| 2 out of 9 hunks FAILED -- rejects in file lib/buffers.c
| patching file lib/gnutls_int.h
| Patch CVE-2026-33845.patch does not apply (enforce with -f)
| 
| stderr: ')
| ERROR: Logfile of failure stored in: .../wrynose/bitbake-builds/poky-wrynose/build/tmp/work/x86-64-v3-poky-linux/gnutls/3.8.12/temp/log.do_patch.240673
| ERROR: Task (.../wrynose/bitbake-builds/poky-wrynose/layers/openembedded-core/meta/recipes-support/gnutls/gnutls_3.8.12.bb:do_patch) failed with exit code '1'

Can you rebase and send a v2?

Thanks!

>
> diff --git a/meta/recipes-support/gnutls/gnutls/CVE-2026-33845.patch b/meta/recipes-support/gnutls/gnutls/CVE-2026-33845.patch
> new file mode 100644
> index 0000000000..d81ffb7ef7
> --- /dev/null
> +++ b/meta/recipes-support/gnutls/gnutls/CVE-2026-33845.patch
> @@ -0,0 +1,195 @@
> +From 9679a9c8ab1694b78c7cb285d29da904e3f3bc45 Mon Sep 17 00:00:00 2001
> +From: Adarsh Jagadish Kamini <adarsh.jagadish.kamini@est.tech>
> +Date: Mon, 27 Jul 2026 08:58:02 +0000
> +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'd think it'd 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>
> +
> +CVE: CVE-2026-33845
> +Upstream-Status: Backport [https://gitlab.com/gnutls/gnutls/-/commit/e5b72c53c7d789d19d1d1cd10b275e87d0415413]
> +
> +Backport notes: adapted to the stable branch, no logic changes.
> +- lib/buffers.c: the local fragment-size variable is named frag_size here,
> +  not frag_length as upstream; renamed accordingly.
> +- lib/buffers.c: merge_handshake_packet() has no recv_buf alias in this
> +  branch, so recv_buf[pos] was expanded to
> +  session->internals.handshake_recv_buffer[pos], which changes line wrapping.
> +- lib/gnutls_int.h: applies cleanly.
> +
> +Assisted-by: kiro:claude-sonnet-4.6
> +Signed-off-by: Adarsh Jagadish Kamini <adarsh.jagadish.kamini@est.tech>
> +---
> + lib/buffers.c    | 57 ++++++++++++++++++++++++------------------------
> + lib/gnutls_int.h |  4 ++--
> + 2 files changed, 31 insertions(+), 30 deletions(-)
> +
> +diff --git a/lib/buffers.c b/lib/buffers.c
> +index 672380b05..2d77e7590 100644
> +--- a/lib/buffers.c
> ++++ b/lib/buffers.c
> +@@ -923,10 +923,7 @@ static int parse_handshake_header(gnutls_session_t session, mbuffer_st *bufel,
> + 	}
> + 	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,10 @@ static int parse_handshake_header(gnutls_session_t session, mbuffer_st *bufel,
> + 
> + 	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 +989,10 @@ static int merge_handshake_packet(gnutls_session_t session,
> + 			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 +1009,7 @@ static int merge_handshake_packet(gnutls_session_t session,
> + 		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 +1018,34 @@ static int merge_handshake_packet(gnutls_session_t session,
> + 			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]
> ++					   .start_offset +
> + 				   session->internals.handshake_recv_buffer[pos]
> +-					   .end_offset &&
> ++					   .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 +1105,8 @@ static int get_last_packet(gnutls_session_t session,
> + 		}
> + 
> + 		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 +1117,9 @@ static int get_last_packet(gnutls_session_t session,
> + 			/* 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 +1306,7 @@ int _gnutls_parse_record_buffered_msgs(gnutls_session_t session)
> + 					&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,
> +@@ -1320,7 +1322,6 @@ int _gnutls_parse_record_buffered_msgs(gnutls_session_t session)
> + 				ret = merge_handshake_packet(session, &tmp);
> + 				if (ret < 0)
> + 					return gnutls_assert_val(ret);
> +-
> + 			} while (_mbuffer_get_udata_size(bufel) > 0);
> + 
> + 			prev = bufel;
> +diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
> +index 54d3c9f67..283f25c07 100644
> +--- a/lib/gnutls_int.h
> ++++ b/lib/gnutls_int.h
> +@@ -479,10 +479,10 @@ typedef struct {
> + 	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; /* used exclusively in DTLS reassembly */
> + 
> + 	uint8_t header[MAX_HANDSHAKE_HEADER_SIZE];
> + 	int header_size;
> diff --git a/meta/recipes-support/gnutls/gnutls_3.8.12.bb b/meta/recipes-support/gnutls/gnutls_3.8.12.bb
> index 468b4bdd40..4219a650de 100644
> --- a/meta/recipes-support/gnutls/gnutls_3.8.12.bb
> +++ b/meta/recipes-support/gnutls/gnutls_3.8.12.bb
> @@ -25,6 +25,7 @@ SRC_URI = "https://www.gnupg.org/ftp/gcrypt/gnutls/v${SHRT_VER}/gnutls-${PV}.tar
>             file://Add-ptest-support.patch \
>             file://c99.patch \
>             file://CVE-2026-3833.patch \
> +           file://CVE-2026-33845.patch \
>             "
>  
>  SRC_URI[sha256sum] = "a7b341421bfd459acf7a374ca4af3b9e06608dcd7bd792b2bf470bea012b8e51"


-- 
Yoann Congal
Smile ECS



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [OE-core][wrynose][PATCH] gnutls: fix CVE-2026-33845
  2026-08-24 15:29 ` Yoann Congal
@ 2026-08-25  8:02   ` Adarsh Jagadish Kamini
  0 siblings, 0 replies; 3+ messages in thread
From: Adarsh Jagadish Kamini @ 2026-08-25  8:02 UTC (permalink / raw)
  To: Yoann Congal, openembedded-core@lists.openembedded.org

On 8/24/26 17:29, Yoann Congal wrote:
> On Mon Jul 27, 2026 at 5:33 PM CEST, Adarsh Jagadish Kamini via lists.openembedded.org wrote:
>> Backport patch to fix CVE-2026-33845.
>>
>> References:
>>    https://nvd.nist.gov/vuln/detail/CVE-2026-33845
>>
>> Upstream fix:
>>    https://gitlab.com/gnutls/gnutls/-/commit/e5b72c53c7d789d19d1d1cd10b275e87d0415413
>>
>> Tested with ptest:
>> Before: PASSED: 371, FAILED: 0, SKIPPED: 15
>> After: PASSED: 371, FAILED: 0, SKIPPED: 15
>>
>> Signed-off-by: Adarsh Jagadish Kamini <adarsh.jagadish.kamini@est.tech>
>> ---
>>   .../gnutls/gnutls/CVE-2026-33845.patch        | 195 ++++++++++++++++++
>>   meta/recipes-support/gnutls/gnutls_3.8.12.bb  |   1 +
>>   2 files changed, 196 insertions(+)
>>   create mode 100644 meta/recipes-support/gnutls/gnutls/CVE-2026-33845.patch
> 
> Hello,
> 
> It looks like this patch does not apply to wrynose anymore:
> | ERROR: gnutls-3.8.12-r0 do_patch: Applying patch '.../wrynose/bitbake-builds/poky-wrynose/layers/openembedded-core/meta/recipes-support/gnutls/gnutls/CVE-2026-33845.patch' on target directory '.../wrynose/bitbake-builds/poky-wrynose/build/tmp/work/x86-64-v3-poky-linux/gnutls/3.8.12/sources/gnutls-3.8.12'
> | CmdError('quilt --quiltrc .../wrynose/bitbake-builds/poky-wrynose/build/tmp/work/x86-64-v3-poky-linux/gnutls/3.8.12/recipe-sysroot-native/etc/quiltrc push', 0, 'stdout: Applying patch CVE-2026-33845.patch
> | patching file lib/buffers.c
> | Hunk #1 succeeded at 919 (offset -4 lines).
> | Hunk #2 succeeded at 933 (offset -4 lines).
> | Hunk #3 succeeded at 1000 (offset 11 lines).
> | Hunk #4 FAILED at 1009.
> | Hunk #5 FAILED at 1018.
> | Hunk #6 succeeded at 1110 (offset 11 lines).
> | Hunk #7 succeeded at 1122 (offset 11 lines).
> | Hunk #8 succeeded at 1311 (offset 11 lines).
> | Hunk #9 succeeded at 1327 (offset 11 lines).
> | 2 out of 9 hunks FAILED -- rejects in file lib/buffers.c
> | patching file lib/gnutls_int.h
> | Patch CVE-2026-33845.patch does not apply (enforce with -f)
> |
> | stderr: ')
> | ERROR: Logfile of failure stored in: .../wrynose/bitbake-builds/poky-wrynose/build/tmp/work/x86-64-v3-poky-linux/gnutls/3.8.12/temp/log.do_patch.240673
> | ERROR: Task (.../wrynose/bitbake-builds/poky-wrynose/layers/openembedded-core/meta/recipes-support/gnutls/gnutls_3.8.12.bb:do_patch) failed with exit code '1'
> 
> Can you rebase and send a v2?
> 
> Thanks!
> 
>>
>> diff --git a/meta/recipes-support/gnutls/gnutls/CVE-2026-33845.patch b/meta/recipes-support/gnutls/gnutls/CVE-2026-33845.patch
>> new file mode 100644
>> index 0000000000..d81ffb7ef7
>> --- /dev/null
>> +++ b/meta/recipes-support/gnutls/gnutls/CVE-2026-33845.patch
>> @@ -0,0 +1,195 @@
>> +From 9679a9c8ab1694b78c7cb285d29da904e3f3bc45 Mon Sep 17 00:00:00 2001
>> +From: Adarsh Jagadish Kamini <adarsh.jagadish.kamini@est.tech>
>> +Date: Mon, 27 Jul 2026 08:58:02 +0000
>> +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'd think it'd 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>
>> +
>> +CVE: CVE-2026-33845
>> +Upstream-Status: Backport [https://gitlab.com/gnutls/gnutls/-/commit/e5b72c53c7d789d19d1d1cd10b275e87d0415413]
>> +
>> +Backport notes: adapted to the stable branch, no logic changes.
>> +- lib/buffers.c: the local fragment-size variable is named frag_size here,
>> +  not frag_length as upstream; renamed accordingly.
>> +- lib/buffers.c: merge_handshake_packet() has no recv_buf alias in this
>> +  branch, so recv_buf[pos] was expanded to
>> +  session->internals.handshake_recv_buffer[pos], which changes line wrapping.
>> +- lib/gnutls_int.h: applies cleanly.
>> +
>> +Assisted-by: kiro:claude-sonnet-4.6
>> +Signed-off-by: Adarsh Jagadish Kamini <adarsh.jagadish.kamini@est.tech>
>> +---
>> + lib/buffers.c    | 57 ++++++++++++++++++++++++------------------------
>> + lib/gnutls_int.h |  4 ++--
>> + 2 files changed, 31 insertions(+), 30 deletions(-)
>> +
>> +diff --git a/lib/buffers.c b/lib/buffers.c
>> +index 672380b05..2d77e7590 100644
>> +--- a/lib/buffers.c
>> ++++ b/lib/buffers.c
>> +@@ -923,10 +923,7 @@ static int parse_handshake_header(gnutls_session_t session, mbuffer_st *bufel,
>> + 	}
>> + 	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,10 @@ static int parse_handshake_header(gnutls_session_t session, mbuffer_st *bufel,
>> +
>> + 	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 +989,10 @@ static int merge_handshake_packet(gnutls_session_t session,
>> + 			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 +1009,7 @@ static int merge_handshake_packet(gnutls_session_t session,
>> + 		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 +1018,34 @@ static int merge_handshake_packet(gnutls_session_t session,
>> + 			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]
>> ++					   .start_offset +
>> + 				   session->internals.handshake_recv_buffer[pos]
>> +-					   .end_offset &&
>> ++					   .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 +1105,8 @@ static int get_last_packet(gnutls_session_t session,
>> + 		}
>> +
>> + 		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 +1117,9 @@ static int get_last_packet(gnutls_session_t session,
>> + 			/* 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 +1306,7 @@ int _gnutls_parse_record_buffered_msgs(gnutls_session_t session)
>> + 					&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,
>> +@@ -1320,7 +1322,6 @@ int _gnutls_parse_record_buffered_msgs(gnutls_session_t session)
>> + 				ret = merge_handshake_packet(session, &tmp);
>> + 				if (ret < 0)
>> + 					return gnutls_assert_val(ret);
>> +-
>> + 			} while (_mbuffer_get_udata_size(bufel) > 0);
>> +
>> + 			prev = bufel;
>> +diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
>> +index 54d3c9f67..283f25c07 100644
>> +--- a/lib/gnutls_int.h
>> ++++ b/lib/gnutls_int.h
>> +@@ -479,10 +479,10 @@ typedef struct {
>> + 	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; /* used exclusively in DTLS reassembly */
>> +
>> + 	uint8_t header[MAX_HANDSHAKE_HEADER_SIZE];
>> + 	int header_size;
>> diff --git a/meta/recipes-support/gnutls/gnutls_3.8.12.bb b/meta/recipes-support/gnutls/gnutls_3.8.12.bb
>> index 468b4bdd40..4219a650de 100644
>> --- a/meta/recipes-support/gnutls/gnutls_3.8.12.bb
>> +++ b/meta/recipes-support/gnutls/gnutls_3.8.12.bb
>> @@ -25,6 +25,7 @@ SRC_URI = "https://www.gnupg.org/ftp/gcrypt/gnutls/v${SHRT_VER}/gnutls-${PV}.tar
>>              file://Add-ptest-support.patch \
>>              file://c99.patch \
>>              file://CVE-2026-3833.patch \
>> +           file://CVE-2026-33845.patch \
>>              "
>>   
>>   SRC_URI[sha256sum] = "a7b341421bfd459acf7a374ca4af3b9e06608dcd7bd792b2bf470bea012b8e51"
> 
> 
Hi,
Yes, will send a v2.

Thanks!


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-08-25 11:02 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-27 15:33 [OE-core][wrynose][PATCH] gnutls: fix CVE-2026-33845 Adarsh Jagadish Kamini
2026-08-24 15:29 ` Yoann Congal
2026-08-25  8:02   ` Adarsh Jagadish Kamini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox