diff --git a/0001-gpg-Fix-possible-memory-corruption-in-the-armor-pars.patch b/0001-gpg-Fix-possible-memory-corruption-in-the-armor-pars.patch new file mode 100644 index 0000000000000000000000000000000000000000..f38893b1aa83e42dbdc26f59a0c34790484fbb83 --- /dev/null +++ b/0001-gpg-Fix-possible-memory-corruption-in-the-armor-pars.patch @@ -0,0 +1,105 @@ +From 9fc375c22650e27fe8b98dd576e95263733e1042 Mon Sep 17 00:00:00 2001 +From: Werner Koch +Date: Thu, 23 Oct 2025 11:36:04 +0200 +Subject: [PATCH] gpg: Fix possible memory corruption in the armor parser. + +* g10/armor.c (armor_filter): Fix faulty double increment. + +* common/iobuf.c (underflow_target): Assert that the filter +implementations behave well. +-- + +This fixes a bug in a code path which can only be reached with special +crafted input data and would then error out at an upper layer due to +corrupt input (every second byte in the buffer is unitialized +garbage). No fuzzing has yet hit this case and we don't have a test +case for this code path. However memory corruption can never be +tolerated as it always has the protential for remode code execution. + +Reported-by: 8b79fe4dd0581c1cd000e1fbecba9f39e16a396a +Fixes-commit: c27c7416d5148865a513e007fb6f0a34993a6073 +which fixed +Fixes-commit: 7d0efec7cf5ae110c99511abc32587ff0c45b14f + +The bug was introduced on 1999-01-07 by me: +* armor.c: Rewrote large parts. +which I fixed on 1999-03-02 but missed to fix the other case: +* armor.c (armor_filter): Fixed armor bypassing. + +Below is base64+gzipped test data which can be used with valgrind to +show access to uninitalized memory in write(2) in the unpatched code. + +--8<---------------cut here---------------start------------->8--- +H4sICIDd+WgCA3h4AO3QMQ6CQBCG0djOKbY3G05gscYFSRAJt/AExp6Di0cQG0ze +a//MV0zOq3Pt+jFN3ZTKfLvP9ZLafqifJUe8juOjeZbVtSkbRPmRgICAgICAgICA +gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA +gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA +gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA +gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA +gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA +gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA +gICAgICAgICAgICAgICAgICAgICAgICAgMCXF6dYDgAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7E14AAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwZ94aieId3+8EAA== +--8<---------------cut here---------------end--------------->8--- +--- + common/iobuf.c | 6 ++++++ + g10/armor.c | 4 ++-- + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/common/iobuf.c b/common/iobuf.c +index 161769a35..969bdc34c 100644 +--- a/common/iobuf.c ++++ b/common/iobuf.c +@@ -2043,6 +2043,8 @@ underflow_target (iobuf_t a, int clear_pending_eof, size_t target) + rc = 0; + else + { ++ size_t tmplen; ++ + /* If no buffered data and drain buffer has been setup, and drain + * buffer is largish, read data directly to drain buffer. */ + if (a->d.len == 0 +@@ -2055,8 +2057,10 @@ underflow_target (iobuf_t a, int clear_pending_eof, size_t target) + log_debug ("iobuf-%d.%d: underflow: A->FILTER (%lu bytes, to external drain)\n", + a->no, a->subno, (ulong)len); + ++ tmplen = len; /* Used to check for bugs in the filter. */ + rc = a->filter (a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain, + a->e_d.buf, &len); ++ log_assert (len <= tmplen); + a->e_d.used = len; + len = 0; + } +@@ -2066,8 +2070,10 @@ underflow_target (iobuf_t a, int clear_pending_eof, size_t target) + log_debug ("iobuf-%d.%d: underflow: A->FILTER (%lu bytes)\n", + a->no, a->subno, (ulong)len); + ++ tmplen = len; + rc = a->filter (a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain, + &a->d.buf[a->d.len], &len); ++ log_assert (len <= tmplen); + } + } + a->d.len += len; +diff --git a/g10/armor.c b/g10/armor.c +index b47c04ab3..39294e257 100644 +--- a/g10/armor.c ++++ b/g10/armor.c +@@ -1302,8 +1302,8 @@ armor_filter( void *opaque, int control, + n = 0; + if( afx->buffer_len ) { + /* Copy the data from AFX->BUFFER to BUF. */ +- for(; n < size && afx->buffer_pos < afx->buffer_len; n++ ) +- buf[n++] = afx->buffer[afx->buffer_pos++]; ++ for(; n < size && afx->buffer_pos < afx->buffer_len;) ++ buf[n++] = afx->buffer[afx->buffer_pos++]; + if( afx->buffer_pos >= afx->buffer_len ) + afx->buffer_len = 0; + } +-- +2.41.1 + diff --git a/gnupg2.spec b/gnupg2.spec index bb0602ab62299589ac373c790048841081658f39..7e524dbb15e656250f505e7ffd1003ff6f06d102 100644 --- a/gnupg2.spec +++ b/gnupg2.spec @@ -1,7 +1,7 @@ Summary: A complete implementation of the OpenPGP to encrypt and sign Name: gnupg2 Version: 2.4.3 -Release: 6%{?dist} +Release: 7%{?dist} License: GPLv3+ URL: https://www.gnupg.org/ Source0: https://gnupg.org/ftp/gcrypt/gnupg/gnupg-%{version}.tar.bz2 @@ -11,6 +11,9 @@ Patch0002: 0002-gpg-Remove-a-signature-check-function-wrapper.patch Patch0003: 0003-gpg-Fix-a-verification-DoS-due-to-a-malicious-subkey.patch Patch0004: 0004-gpg-Fix-regression-for-the-recent-malicious-subkey-D.patch Patch0005: 0005-gpg-Fix-double-free-of-internal-data.patch +# CVE-2025-68973 +Patch0006: 0001-gpg-Fix-possible-memory-corruption-in-the-armor-pars.patch + Patch3000: gnupg-2.1.10-secmem.patch Patch3001: gnupg-2.1.1-fips-algo.patch @@ -167,6 +170,9 @@ make check %changelog +* Wed Dec 31 2025 Miaojun Dong - 2.4.3-7 +- Fix CVE-2025-68973 + * Wed Apr 16 2025 Sinong Chen - 2.4.3-6 - Add support for sm2 and sm3 algorithms