Fix CVE-2026-45447: Heap Use-After-Free in OpenSSL PKCS7_verify()
Resolves: RHEL-179623
This commit is contained in:
parent
63ea9a612a
commit
cb1946c30a
260
openssl-1.1.1-cve-2026-45447.patch
Normal file
260
openssl-1.1.1-cve-2026-45447.patch
Normal file
@ -0,0 +1,260 @@
|
||||
From 4ae990ae9c7f47ac214527dc5685e5df0c82d6b9 Mon Sep 17 00:00:00 2001
|
||||
From: Dmitry Belyavskiy <beldmit@gmail.com>
|
||||
Date: Tue, 2 Jun 2026 14:55:02 +0200
|
||||
Subject: [PATCH] Fix double-free of caller-owned BIO in PKCS7_verify
|
||||
|
||||
When PKCS7_dataInit creates no filter BIOs (e.g. empty digestAlgorithms
|
||||
SET), it returns p7bio pointing directly to the caller's indata BIO.
|
||||
The cleanup code in PKCS7_verify then frees indata via BIO_free_all(p7bio),
|
||||
leaving the caller with a dangling pointer and causing a double-free
|
||||
when the caller frees its own BIO.
|
||||
|
||||
Guard BIO_free_all with a check that p7bio is not the caller's indata BIO.
|
||||
|
||||
Add a regression test using a crafted S/MIME message with an empty
|
||||
digestAlgorithms SET to verify the fix.
|
||||
|
||||
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
||||
---
|
||||
crypto/pkcs7/pk7_smime.c | 5 +-
|
||||
test/build.info | 7 +-
|
||||
test/pkcs7_verify_test.c | 104 ++++++++++++++++++
|
||||
test/recipes/25-test_pkcs7_verify.t | 20 ++++
|
||||
.../pkcs7-empty-digest-set.eml | 45 ++++++++
|
||||
5 files changed, 179 insertions(+), 2 deletions(-)
|
||||
create mode 100644 test/pkcs7_verify_test.c
|
||||
create mode 100644 test/recipes/25-test_pkcs7_verify.t
|
||||
create mode 100644 test/recipes/25-test_pkcs7_verify_data/pkcs7-empty-digest-set.eml
|
||||
|
||||
diff --git a/crypto/pkcs7/pk7_smime.c b/crypto/pkcs7/pk7_smime.c
|
||||
index a95db62178..3e3ceda3cf 100644
|
||||
--- a/crypto/pkcs7/pk7_smime.c
|
||||
+++ b/crypto/pkcs7/pk7_smime.c
|
||||
@@ -363,8 +363,11 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
|
||||
if (tmpin == indata) {
|
||||
if (indata)
|
||||
BIO_pop(p7bio);
|
||||
+ if (p7bio != indata)
|
||||
+ BIO_free_all(p7bio);
|
||||
+ } else {
|
||||
+ BIO_free_all(p7bio);
|
||||
}
|
||||
- BIO_free_all(p7bio);
|
||||
sk_X509_free(signers);
|
||||
return ret;
|
||||
}
|
||||
diff --git a/test/build.info b/test/build.info
|
||||
index 6357a7f2fe..648be6bbfc 100644
|
||||
--- a/test/build.info
|
||||
+++ b/test/build.info
|
||||
@@ -51,7 +51,8 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=MAIN
|
||||
recordlentest drbgtest drbg_cavs_test sslbuffertest \
|
||||
time_offset_test pemtest ssl_cert_table_internal_test ciphername_test \
|
||||
servername_test ocspapitest rsa_mp_test fatalerrtest tls13ccstest \
|
||||
- sysdefaulttest errtest ssl_ctx_test gosttest
|
||||
+ sysdefaulttest errtest ssl_ctx_test gosttest \
|
||||
+ pkcs7_verify_test
|
||||
|
||||
SOURCE[versions]=versions.c
|
||||
INCLUDE[versions]=../include
|
||||
@@ -574,6 +575,10 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=MAIN
|
||||
INCLUDE[ssl_ctx_test]=../include
|
||||
DEPEND[ssl_ctx_test]=../libcrypto ../libssl libtestutil.a
|
||||
|
||||
+ SOURCE[pkcs7_verify_test]=pkcs7_verify_test.c
|
||||
+ INCLUDE[pkcs7_verify_test]=../include
|
||||
+ DEPEND[pkcs7_verify_test]=../libcrypto libtestutil.a
|
||||
+
|
||||
{-
|
||||
use File::Spec::Functions;
|
||||
use File::Basename;
|
||||
diff --git a/test/pkcs7_verify_test.c b/test/pkcs7_verify_test.c
|
||||
new file mode 100644
|
||||
index 0000000000..932c2589ae
|
||||
--- /dev/null
|
||||
+++ b/test/pkcs7_verify_test.c
|
||||
@@ -0,0 +1,104 @@
|
||||
+/*
|
||||
+ * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved.
|
||||
+ *
|
||||
+ * Licensed under the OpenSSL license (the "License"). You may not use
|
||||
+ * this file except in compliance with the License. You can obtain a copy
|
||||
+ * in the file LICENSE in the source distribution or at
|
||||
+ * https://www.openssl.org/source/license.html
|
||||
+ */
|
||||
+
|
||||
+#include <openssl/pkcs7.h>
|
||||
+#include <openssl/bio.h>
|
||||
+#include <openssl/err.h>
|
||||
+#include <openssl/objects.h>
|
||||
+#include "testutil.h"
|
||||
+
|
||||
+static const char *emlfile;
|
||||
+
|
||||
+/*
|
||||
+ * Regression test for a double-free of the caller-owned indata BIO in
|
||||
+ * PKCS7_verify. When the PKCS7 digestAlgorithms SET is empty,
|
||||
+ * PKCS7_dataInit creates no digest filter BIOs and returns p7bio == indata.
|
||||
+ * The cleanup code then frees the caller's BIO via BIO_free_all(p7bio).
|
||||
+ *
|
||||
+ * The test uses a crafted S/MIME message whose PKCS7 signature has an empty
|
||||
+ * digestAlgorithms SET. The detached content is re-wrapped through a
|
||||
+ * file-backed BIO to bypass the tmpin memory-BIO optimisation in
|
||||
+ * PKCS7_verify (which would mask the bug).
|
||||
+ */
|
||||
+static int test_pkcs7_verify_empty_md_algs(void)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+ BIO *bio_eml = NULL;
|
||||
+ BIO *indata_mem = NULL;
|
||||
+ BIO *indata = NULL;
|
||||
+ PKCS7 *p7 = NULL;
|
||||
+ char *mem_ptr = NULL;
|
||||
+ long mem_len;
|
||||
+ FILE *tmpf = NULL;
|
||||
+
|
||||
+ if (!TEST_ptr(bio_eml = BIO_new_file(emlfile, "r")))
|
||||
+ goto err;
|
||||
+
|
||||
+ if (!TEST_ptr(p7 = SMIME_read_PKCS7(bio_eml, &indata_mem)))
|
||||
+ goto err;
|
||||
+
|
||||
+ /* Confirm the test data has an empty digestAlgorithms SET */
|
||||
+ if (!TEST_int_eq(sk_X509_ALGOR_num(p7->d.sign->md_algs), 0))
|
||||
+ goto err;
|
||||
+
|
||||
+ /*
|
||||
+ * Re-wrap content through a file BIO so BIO_method_type != BIO_TYPE_MEM.
|
||||
+ * This forces tmpin == indata in PKCS7_verify, hitting the vulnerable path.
|
||||
+ */
|
||||
+ mem_len = BIO_get_mem_data(indata_mem, &mem_ptr);
|
||||
+ if (!TEST_ptr(tmpf = tmpfile()))
|
||||
+ goto err;
|
||||
+ if (fwrite(mem_ptr, 1, mem_len, tmpf) != (size_t)mem_len) {
|
||||
+ fclose(tmpf);
|
||||
+ TEST_error("failed to write to temp file");
|
||||
+ goto err;
|
||||
+ }
|
||||
+ fflush(tmpf);
|
||||
+ rewind(tmpf);
|
||||
+ if (!TEST_ptr(indata = BIO_new_fp(tmpf, BIO_CLOSE))) {
|
||||
+ fclose(tmpf);
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * NOVERIFY: skip cert chain validation
|
||||
+ * NOSIGS: skip signature verification
|
||||
+ * We only care about the BIO lifecycle, not cryptographic validity.
|
||||
+ */
|
||||
+ PKCS7_verify(p7, NULL, NULL, indata, NULL,
|
||||
+ PKCS7_NOVERIFY | PKCS7_NOSIGS);
|
||||
+
|
||||
+ /*
|
||||
+ * If the bug is present, indata has already been freed by PKCS7_verify.
|
||||
+ * BIO_free will crash (use-after-free / double-free). Under ASan this
|
||||
+ * is detected reliably; without ASan it may silently corrupt the heap.
|
||||
+ */
|
||||
+ BIO_free(indata);
|
||||
+ indata = NULL;
|
||||
+
|
||||
+ ret = 1;
|
||||
+
|
||||
+err:
|
||||
+ BIO_free(indata);
|
||||
+ BIO_free(indata_mem);
|
||||
+ PKCS7_free(p7);
|
||||
+ BIO_free(bio_eml);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+int setup_tests(void)
|
||||
+{
|
||||
+ if (!TEST_ptr(emlfile = test_get_argument(0))) {
|
||||
+ TEST_note("usage: pkcs7_verify_test <eml-file>");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ ADD_TEST(test_pkcs7_verify_empty_md_algs);
|
||||
+ return 1;
|
||||
+}
|
||||
diff --git a/test/recipes/25-test_pkcs7_verify.t b/test/recipes/25-test_pkcs7_verify.t
|
||||
new file mode 100644
|
||||
index 0000000000..7666467f8c
|
||||
--- /dev/null
|
||||
+++ b/test/recipes/25-test_pkcs7_verify.t
|
||||
@@ -0,0 +1,20 @@
|
||||
+#! /usr/bin/env perl
|
||||
+# Copyright 2026 The OpenSSL Project Authors. All Rights Reserved.
|
||||
+#
|
||||
+# Licensed under the OpenSSL license (the "License"). You may not use
|
||||
+# this file except in compliance with the License. You can obtain a copy
|
||||
+# in the file LICENSE in the source distribution or at
|
||||
+# https://www.openssl.org/source/license.html
|
||||
+
|
||||
+use strict;
|
||||
+use warnings;
|
||||
+
|
||||
+use OpenSSL::Test qw/:DEFAULT data_file/;
|
||||
+
|
||||
+setup("test_pkcs7_verify");
|
||||
+
|
||||
+plan tests => 1;
|
||||
+
|
||||
+ok(run(test(["pkcs7_verify_test",
|
||||
+ data_file("pkcs7-empty-digest-set.eml")])),
|
||||
+ "PKCS7_verify with empty digestAlgorithms does not double-free indata");
|
||||
diff --git a/test/recipes/25-test_pkcs7_verify_data/pkcs7-empty-digest-set.eml b/test/recipes/25-test_pkcs7_verify_data/pkcs7-empty-digest-set.eml
|
||||
new file mode 100644
|
||||
index 0000000000..a6db2c38ad
|
||||
--- /dev/null
|
||||
+++ b/test/recipes/25-test_pkcs7_verify_data/pkcs7-empty-digest-set.eml
|
||||
@@ -0,0 +1,45 @@
|
||||
+MIME-Version: 1.0
|
||||
+Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----E0314CC5D732C92AE2D7A3BACDCDCFCE"
|
||||
+
|
||||
+This is an S/MIME signed message
|
||||
+
|
||||
+------E0314CC5D732C92AE2D7A3BACDCDCFCE
|
||||
+This is the content to be signed.
|
||||
+
|
||||
+------E0314CC5D732C92AE2D7A3BACDCDCFCE
|
||||
+Content-Type: application/x-pkcs7-signature; name="smime.p7s"
|
||||
+Content-Transfer-Encoding: base64
|
||||
+Content-Disposition: attachment; filename="smime.p7s"
|
||||
+
|
||||
+MIIFWgYJKoZIhvcNAQcCoIIFSzCCBUcCAQExADALBgkqhkiG9w0BBwGgggLuMIIC
|
||||
+6jCCAdKgAwIBAgIUL5E46FxyhsT7C3G1NS27OtR7XAowDQYJKoZIhvcNAQELBQAw
|
||||
+FTETMBEGA1UEAwwKUG9DIFNpZ25lcjAeFw0yNjA1MDgxMDIwNDhaFw0yNzA1MDgx
|
||||
+MDIwNDhaMBUxEzARBgNVBAMMClBvQyBTaWduZXIwggEiMA0GCSqGSIb3DQEBAQUA
|
||||
+A4IBDwAwggEKAoIBAQDSSu/gupmIlclvmTMHiqOrCqmB8NRTjAMoI//MPJrnFXYp
|
||||
+FjDPMk7Y/kCcHztudaIvADkowaFtOm4oMinQFhjwCNCo5K5WrrlAitnpcd5QH2nA
|
||||
+iVZXjjohQUJEd7n33AGqTwo5EGaCK+alAZL7tA7bdhNi/aZ33L3bUNYqoHbXiNsE
|
||||
+u1tj8frLfIjduOt0TMPSOrrFjjEsrL3T3tg+HmxpalDHz7E6o9zJu0wlk8bcR2Xk
|
||||
+mpX8RdYCu7K9m39N1F2WKa9WJh24NQLpWRfwD213jaIFK2EXy/XHePDUeiMYtVOV
|
||||
+oovCSmY7OqowupA7J+4dcsnRjFqgZECctHhAfk+PAgMBAAGjMjAwMB0GA1UdDgQW
|
||||
+BBRZlupXNYq4fny0SE76sr/CdQ2DUTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
|
||||
+DQEBCwUAA4IBAQANOlttTWVz620JNTrPzhiR4x9+5UiF4GSqv8BRJQFj3Xh7fsUp
|
||||
++3GDs9M27f4FVh3utJsjt7Sa9ZWLpBVdgjGBwGLAtPsoYMjhnUgZTUvwEk5+aXyv
|
||||
+zJxn4I7mMbDhlNCMHcVtGdtA+2UOEuvdGfuEilpzPsV8DzM1K3xU5bSWoo0BRFKK
|
||||
+srHkyEfxCFPAQOcX80ZbMO6zdcXeJjC6mQXGqy2aqeQob0vuSZJ7QHZBlRjY5YHR
|
||||
+wWlIqG8G3Eist16iTqdX2PQFZT1/QAEQ/LnXARTUUjUroccdci8YNASoeHDpcjRL
|
||||
+MBrN+QBNZVt5qLhDogwZb2ZwqKfZ8Aqg3oAkMYICPzCCAjsCAQEwLTAVMRMwEQYD
|
||||
+VQQDDApQb0MgU2lnbmVyAhQvkTjoXHKGxPsLcbU1Lbs61HtcCjANBglghkgBZQME
|
||||
+AgEFAKCB5DAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEP
|
||||
+Fw0yNjA1MDgxMDIwNDhaMC8GCSqGSIb3DQEJBDEiBCAvyoHfycLqb8UzVPizy1uA
|
||||
+o3h7tza3HebeiJaSnpIJHzB5BgkqhkiG9w0BCQ8xbDBqMAsGCWCGSAFlAwQBKjAL
|
||||
+BglghkgBZQMEARYwCwYJYIZIAWUDBAECMAoGCCqGSIb3DQMHMA4GCCqGSIb3DQMC
|
||||
+AgIAgDANBggqhkiG9w0DAgIBQDAHBgUrDgMCBzANBggqhkiG9w0DAgIBKDANBgkq
|
||||
+hkiG9w0BAQEFAASCAQBIpl7U2j4YiU1vdZHyx2dCK41ZahtTVOB4RVJcrmopgans
|
||||
+fICdkSTfb0dVqc13++bYn4i1b2R2os5YIkoGxdrM5aZB7KF9r1xwgrendTF4/BwP
|
||||
+gQq2khNtKebv9Yr0kOPynFIsgx5BHk99wrzfwidJUFuJJgQ9W0YOf7EGkbnZvPT+
|
||||
+hV0aeLmJAb5jjWhbDciqUjR3O23JQhzVj4U3vo2TeN7VYmNJsX+fA4sZzIbYSei9
|
||||
+ps7GZruiRcKgqgUj1l8HjIGMHqd9lccchk/BYyAGxAbgGisntvfJdPZO09wG8rHh
|
||||
+eS6FYkkXAKBO49WbhE9aVLJH0zgA6gTfyEvOOOS1
|
||||
+
|
||||
+------E0314CC5D732C92AE2D7A3BACDCDCFCE--
|
||||
+
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
Summary: Utilities from the general purpose cryptography library with TLS implementation
|
||||
Name: openssl
|
||||
Version: 1.1.1k
|
||||
Release: 15%{?dist}
|
||||
Release: 16%{?dist}
|
||||
Epoch: 1
|
||||
# We have to remove certain patented algorithms from the openssl source
|
||||
# tarball with the hobble-openssl script which is included below.
|
||||
@ -107,6 +107,7 @@ Patch111: openssl-1.1.1-ticket_lifetime_hint.patch
|
||||
# Fix for CVE-2025-69419
|
||||
Patch112: openssl-1.1.1-hardening-from-openssl-3.0.1.patch
|
||||
Patch113: openssl-1.1.1-cve-2025-69419.patch
|
||||
Patch114: openssl-1.1.1-cve-2026-45447.patch
|
||||
|
||||
License: OpenSSL and ASL 2.0
|
||||
URL: http://www.openssl.org/
|
||||
@ -245,6 +246,7 @@ cp %{SOURCE13} test/
|
||||
%patch111 -p1 -b .ticket_lifetime_hint
|
||||
%patch112 -p1 -b .cve-2025-69419-1
|
||||
%patch113 -p1 -b .cve-2025-69419-2
|
||||
%patch114 -p1 -b .cve-2026-45447
|
||||
|
||||
%build
|
||||
# Figure out which flags we want to use.
|
||||
@ -528,6 +530,10 @@ export LD_LIBRARY_PATH
|
||||
%postun libs -p /sbin/ldconfig
|
||||
|
||||
%changelog
|
||||
* Mon Jun 01 2026 Dmitry Belyavskiy <dbelyavs@redhat.com> - 1:1.1.1k-16
|
||||
- Fix CVE-2026-45447: Heap Use-After-Free in OpenSSL PKCS7_verify()
|
||||
Resolves: RHEL-179623
|
||||
|
||||
* Thu Feb 12 2026 Antonio Vieiro <avieirov@redhat.com> - 1:1.1.1k-15
|
||||
- Fix CVE-2025-69419: Arbitrary code execution due to out-of-bounds write in PKCS#12 processing
|
||||
Resolves: RHEL-142010
|
||||
|
||||
Loading…
Reference in New Issue
Block a user