mirror of
https://github.com/openembedded/meta-openembedded.git
synced 2026-09-26 00:11:04 +00:00
thrift: fix CVE-2026-48586
Improper Handling of Highly Compressed Data (Data Amplification) vulnerability in Apache Thrift C++, Java, Python, Go, D, C/GLib bindings. This issue affects Apache Thrift: before 0.24.0. Backport patch to fix CVE-2026-48586. Reference: [https://nvd.nist.gov/vuln/detail/cve-2026-48586] Upstream Patch: [https://github.com/apache/thrift/commit/e3c8c534cacdbef039f4bb0bcf4b2744a982e3bf] [https://github.com/apache/thrift/commit/702d00f9053133aba7186f2dbb242a91a1ddd491] Signed-off-by: Abhishek Bachiphale <Abhishek.Bachiphale@windriver.com> Signed-off-by: Anuj Mittal <anuj.mittal@oss.qualcomm.com>
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
From e3c8c534cacdbef039f4bb0bcf4b2744a982e3bf Mon Sep 17 00:00:00 2001
|
||||
From: Jens Geyer <jensg@apache.org>
|
||||
Date: Thu, 21 May 2026 14:24:28 +0200
|
||||
Subject: [PATCH] Add decompressed byte tracking to C++ TZlibTransport Client:
|
||||
cpp
|
||||
|
||||
TZlibTransport::read() called checkReadBytesAvailable() but never
|
||||
called countConsumedMessageBytes(), so remainingMessageSize_ was never
|
||||
decremented. Each read() call would pass the check regardless of how
|
||||
many bytes had already been decompressed. Add countConsumedMessageBytes()
|
||||
after each copy from the inflate buffer so that the TConfiguration
|
||||
maxMessageSize limit is correctly enforced across the lifetime of a
|
||||
decompression session.
|
||||
|
||||
Also adds test_message_size_limit() to ZlibTest to cover this path.
|
||||
|
||||
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
||||
|
||||
CVE: CVE-2026-48586
|
||||
Upstream-Status: Backport [https://github.com/apache/thrift/commit/e3c8c534cacdbef039f4bb0bcf4b2744a982e3bf]
|
||||
Signed-off-by: Abhishek Bachiphale <Abhishek.Bachiphale@windriver.com>
|
||||
---
|
||||
.../src/thrift/transport/TZlibTransport.cpp | 1 +
|
||||
lib/cpp/test/ZlibTest.cpp | 37 +++++++++++++++++++
|
||||
2 files changed, 38 insertions(+)
|
||||
|
||||
diff --git a/lib/cpp/src/thrift/transport/TZlibTransport.cpp b/lib/cpp/src/thrift/transport/TZlibTransport.cpp
|
||||
index 1a171109837..d6161a129d9 100644
|
||||
--- a/lib/cpp/src/thrift/transport/TZlibTransport.cpp
|
||||
+++ b/lib/cpp/src/thrift/transport/TZlibTransport.cpp
|
||||
@@ -149,6 +149,7 @@ uint32_t TZlibTransport::read(uint8_t* buf, uint32_t len) {
|
||||
need -= give;
|
||||
buf += give;
|
||||
urpos_ += give;
|
||||
+ countConsumedMessageBytes(give);
|
||||
|
||||
// If they were satisfied, we are done.
|
||||
if (need == 0) {
|
||||
diff --git a/lib/cpp/test/ZlibTest.cpp b/lib/cpp/test/ZlibTest.cpp
|
||||
index ea9c617f625..8f8f5a8e7cf 100644
|
||||
--- a/lib/cpp/test/ZlibTest.cpp
|
||||
+++ b/lib/cpp/test/ZlibTest.cpp
|
||||
@@ -45,8 +45,10 @@
|
||||
|
||||
#include <thrift/transport/TBufferTransports.h>
|
||||
#include <thrift/transport/TZlibTransport.h>
|
||||
+#include <thrift/TConfiguration.h>
|
||||
|
||||
using namespace apache::thrift::transport;
|
||||
+using apache::thrift::TConfiguration;
|
||||
using std::shared_ptr;
|
||||
using std::string;
|
||||
|
||||
@@ -338,6 +340,38 @@ void test_get_underlying_transport() {
|
||||
BOOST_CHECK_EQUAL(membuf.get(), zlib_trans->getUnderlyingTransport().get());
|
||||
}
|
||||
|
||||
+void test_message_size_limit() {
|
||||
+ // Write 4 KB of compressible data, then read it back with a 1 KB limit.
|
||||
+ const uint32_t write_len = 4096;
|
||||
+ boost::shared_array<uint8_t> buf = gen_uniform_buffer(write_len, 'a');
|
||||
+
|
||||
+ shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer());
|
||||
+ {
|
||||
+ shared_ptr<TZlibTransport> writer(new TZlibTransport(membuf));
|
||||
+ writer->write(buf.get(), write_len);
|
||||
+ writer->finish();
|
||||
+ }
|
||||
+
|
||||
+ auto config = std::make_shared<TConfiguration>();
|
||||
+ config->setMaxMessageSize(1024);
|
||||
+ shared_ptr<TZlibTransport> reader(new TZlibTransport(
|
||||
+ membuf,
|
||||
+ TZlibTransport::DEFAULT_URBUF_SIZE,
|
||||
+ TZlibTransport::DEFAULT_CRBUF_SIZE,
|
||||
+ TZlibTransport::DEFAULT_UWBUF_SIZE,
|
||||
+ TZlibTransport::DEFAULT_CWBUF_SIZE,
|
||||
+ Z_DEFAULT_COMPRESSION,
|
||||
+ config));
|
||||
+
|
||||
+ boost::shared_array<uint8_t> mirror(new uint8_t[write_len]);
|
||||
+ try {
|
||||
+ reader->readAll(mirror.get(), write_len);
|
||||
+ BOOST_ERROR("readAll() should have thrown when maxMessageSize is exceeded");
|
||||
+ } catch (TTransportException& ex) {
|
||||
+ BOOST_CHECK_EQUAL(ex.getType(), TTransportException::END_OF_FILE);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Initialization
|
||||
*/
|
||||
@@ -441,6 +475,7 @@ bool init_unit_test_suite() {
|
||||
|
||||
suite->add(BOOST_TEST_CASE(test_no_write));
|
||||
suite->add(BOOST_TEST_CASE(test_get_underlying_transport));
|
||||
+ suite->add(BOOST_TEST_CASE(test_message_size_limit));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -467,6 +502,8 @@ boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) {
|
||||
add_tests(suite, gen_random_buffer(buf_len), buf_len, "random");
|
||||
|
||||
suite->add(BOOST_TEST_CASE(test_no_write));
|
||||
+ suite->add(BOOST_TEST_CASE(test_get_underlying_transport));
|
||||
+ suite->add(BOOST_TEST_CASE(test_message_size_limit));
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
From 702d00f9053133aba7186f2dbb242a91a1ddd491 Mon Sep 17 00:00:00 2001
|
||||
From: Jens Geyer <jensg@apache.org>
|
||||
Date: Thu, 21 May 2026 22:29:35 +0200
|
||||
Subject: [PATCH] Add consumed byte tracking to ThriftZlibTransport read
|
||||
Client: c_glib
|
||||
|
||||
Call countConsumedMessageBytes() after each successful read so that
|
||||
the pre-existing checkReadBytesAvailable() limit is decremented per
|
||||
the transport's message size configuration.
|
||||
|
||||
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
||||
CVE: CVE-2026-48586
|
||||
Upstream-Status: Backport [https://github.com/apache/thrift/commit/702d00f9053133aba7186f2dbb242a91a1ddd491]
|
||||
Signed-off-by: Abhishek Bachiphale <Abhishek.Bachiphale@windriver.com>
|
||||
---
|
||||
.../c_glib/transport/thrift_zlib_transport.c | 4 +++
|
||||
lib/c_glib/test/testzlibtransport.c | 26 +++++++++++++++++++
|
||||
2 files changed, 30 insertions(+)
|
||||
|
||||
diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_zlib_transport.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_zlib_transport.c
|
||||
index 32f1ba27d74..459d08f79bc 100644
|
||||
--- a/lib/c_glib/src/thrift/c_glib/transport/thrift_zlib_transport.c
|
||||
+++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_zlib_transport.c
|
||||
@@ -238,6 +238,10 @@ thrift_zlib_transport_read (ThriftTransport *transport, gpointer buf,
|
||||
break;
|
||||
}
|
||||
|
||||
+ if (!ttc->countConsumedMessageBytes (transport, i, error)) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
return len;
|
||||
}
|
||||
|
||||
diff --git a/lib/c_glib/test/testzlibtransport.c b/lib/c_glib/test/testzlibtransport.c
|
||||
index 04e368ffa93..531241acd7f 100644
|
||||
--- a/lib/c_glib/test/testzlibtransport.c
|
||||
+++ b/lib/c_glib/test/testzlibtransport.c
|
||||
@@ -214,6 +214,31 @@ thrift_server (const int port)
|
||||
g_object_unref (tsocket);
|
||||
}
|
||||
|
||||
+static void
|
||||
+test_message_size_limit(void)
|
||||
+{
|
||||
+ ThriftSocket *tsocket = NULL;
|
||||
+ ThriftTransport *transport = NULL;
|
||||
+ gchar readbuf[4096];
|
||||
+ GError *err = NULL;
|
||||
+ gint32 ret;
|
||||
+
|
||||
+ /* checkReadBytesAvailable fires before any I/O, so the underlying transport
|
||||
+ * does not need to be connected or contain data. */
|
||||
+ tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
|
||||
+ "port", 9999, NULL);
|
||||
+ transport = g_object_new (THRIFT_TYPE_ZLIB_TRANSPORT,
|
||||
+ "transport", THRIFT_TRANSPORT (tsocket),
|
||||
+ "remainingmessagesize", (glong) 1024,
|
||||
+ NULL);
|
||||
+
|
||||
+ ret = thrift_zlib_transport_read (transport, readbuf, sizeof (readbuf), &err);
|
||||
+ g_assert (ret < 0);
|
||||
+ if (err) g_error_free (err);
|
||||
+ g_object_unref (transport);
|
||||
+ g_object_unref (tsocket);
|
||||
+}
|
||||
+
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
@@ -226,6 +251,7 @@ main(int argc, char *argv[])
|
||||
g_test_add_func ("/testzlibtransport/CreateAndDestroy", test_create_and_destroy);
|
||||
g_test_add_func ("/testzlibtransport/OpenAndClose", test_open_and_close);
|
||||
g_test_add_func ("/testzlibtransport/ReadAndWrite", test_read_and_write);
|
||||
+ g_test_add_func ("/testzlibtransport/MessageSizeLimit", test_message_size_limit);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
@@ -22,6 +22,8 @@ SRC_URI = "https://downloads.apache.org/${BPN}/${PV}/${BP}.tar.gz \
|
||||
file://CVE-2026-45112.patch \
|
||||
file://CVE-2026-55969.patch \
|
||||
file://CVE-2026-55970.patch \
|
||||
file://CVE-2026-48586-01.patch \
|
||||
file://CVE-2026-48586-02.patch \
|
||||
"
|
||||
SRC_URI[sha256sum] = "794a0e455787960d9f27ab92c38e34da27e8deeda7a5db0e59dc64a00df8a1e5"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user