mirror of
https://github.com/openembedded/meta-openembedded.git
synced 2026-10-23 08:48:24 +00:00
thrift: fix CVE-2026-55969
Backport patch to fix CVE-2026-55969. References: https://nvd.nist.gov/vuln/detail/CVE-2026-55969 Upstream fix: https://github.com/apache/thrift/commit/983c813c9a1a2302d9a3ae23d7368beceaac2d0a Signed-off-by: Adarsh Jagadish Kamini <adarsh.jagadish.kamini@est.tech> Signed-off-by: Anuj Mittal <anuj.mittal@oss.qualcomm.com>
This commit is contained in:
1 parent
244521fbe6
commit
fe4f335ffe
2 files changed
+296
No files matched your search
@@ -0,0 +1,295 @@
|
|||||||
|
From f288d1a7bdd994872d6ac1e7f2d7eb60b5beb1e5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: dxbjavid <dxbjavid@gmail.com>
|
||||||
|
Date: Tue, 9 Jun 2026 16:35:58 +0530
|
||||||
|
Subject: [PATCH] Widen multiplication operands in container size prechecks to
|
||||||
|
prevent arithmetic overflow on LLP64 platforms Client: cpp,c_glib Patch:
|
||||||
|
Javid Khan
|
||||||
|
|
||||||
|
This closes #3590
|
||||||
|
|
||||||
|
Backport note: in thrift_binary_protocol.c the 0.22.0 tree lacks the
|
||||||
|
container_limit property infrastructure present upstream (unrelated to this
|
||||||
|
CVE), so only the intended change was applied: widening the sizei/msize
|
||||||
|
multiplication operands to gint64 in the checkReadBytesAvailable calls.
|
||||||
|
|
||||||
|
Assisted-by: kiro:claude-sonnet-5
|
||||||
|
|
||||||
|
CVE: CVE-2026-55969
|
||||||
|
Upstream-Status: Backport [https://github.com/apache/thrift/commit/983c813c9a1a2302d9a3ae23d7368beceaac2d0a]
|
||||||
|
|
||||||
|
Signed-off-by: Adarsh Jagadish Kamini <adarsh.jagadish.kamini@est.tech>
|
||||||
|
---
|
||||||
|
.../c_glib/protocol/thrift_binary_protocol.c | 6 +--
|
||||||
|
.../c_glib/protocol/thrift_compact_protocol.c | 10 ++--
|
||||||
|
.../c_glib/transport/thrift_transport.c | 2 +-
|
||||||
|
.../c_glib/transport/thrift_transport.h | 2 +-
|
||||||
|
lib/cpp/src/thrift/protocol/TBinaryProtocol.h | 6 +--
|
||||||
|
.../src/thrift/protocol/TCompactProtocol.h | 6 +--
|
||||||
|
lib/cpp/src/thrift/protocol/TJSONProtocol.h | 6 +--
|
||||||
|
lib/cpp/src/thrift/protocol/TProtocol.h | 6 +--
|
||||||
|
lib/cpp/src/thrift/transport/TTransport.h | 3 +-
|
||||||
|
lib/cpp/test/ThrifttReadCheckTests.cpp | 48 +++++++++++++++++++
|
||||||
|
10 files changed, 72 insertions(+), 23 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.c b/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.c
|
||||||
|
index 9e80e107c..3bad603c3 100644
|
||||||
|
--- a/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.c
|
||||||
|
+++ b/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.c
|
||||||
|
@@ -562,8 +562,8 @@ thrift_binary_protocol_read_map_begin (ThriftProtocol *protocol,
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ttc->checkReadBytesAvailable (THRIFT_TRANSPORT(tp->transport),
|
||||||
|
- sizei * thrift_binary_protocol_get_min_serialized_size(protocol, k, error) +
|
||||||
|
- sizei * thrift_binary_protocol_get_min_serialized_size(protocol, v, error),
|
||||||
|
+ (gint64) sizei * thrift_binary_protocol_get_min_serialized_size(protocol, k, error) +
|
||||||
|
+ (gint64) sizei * thrift_binary_protocol_get_min_serialized_size(protocol, v, error),
|
||||||
|
error))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
@@ -619,7 +619,7 @@ thrift_binary_protocol_read_list_begin (ThriftProtocol *protocol,
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ttc->checkReadBytesAvailable (THRIFT_TRANSPORT(tp->transport),
|
||||||
|
- (sizei * thrift_binary_protocol_get_min_serialized_size(protocol, e, error)),
|
||||||
|
+ ((gint64) sizei * thrift_binary_protocol_get_min_serialized_size(protocol, e, error)),
|
||||||
|
error))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
diff --git a/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.c b/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.c
|
||||||
|
index 0aa9a6fe6..f6ad36b36 100644
|
||||||
|
--- a/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.c
|
||||||
|
+++ b/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.c
|
||||||
|
@@ -1108,9 +1108,9 @@ thrift_compact_protocol_read_map_begin (ThriftProtocol *protocol,
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if(!ttc->checkReadBytesAvailable (THRIFT_TRANSPORT (tp->transport),
|
||||||
|
- msize * thrift_protocol_get_min_serialized_size (protocol, *key_type, error) +
|
||||||
|
- msize * thrift_protocol_get_min_serialized_size (protocol, *value_type, error),
|
||||||
|
+ if(!ttc->checkReadBytesAvailable (THRIFT_TRANSPORT (tp->transport),
|
||||||
|
+ (gint64) msize * thrift_protocol_get_min_serialized_size (protocol, *key_type, error) +
|
||||||
|
+ (gint64) msize * thrift_protocol_get_min_serialized_size (protocol, *value_type, error),
|
||||||
|
error))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
@@ -1183,8 +1183,8 @@ thrift_compact_protocol_read_list_begin (ThriftProtocol *protocol,
|
||||||
|
*element_type = ret;
|
||||||
|
*size = (guint32) lsize;
|
||||||
|
|
||||||
|
- if(!ttc->checkReadBytesAvailable (THRIFT_TRANSPORT (tp->transport),
|
||||||
|
- (lsize * thrift_protocol_get_min_serialized_size (protocol, *element_type, error)),
|
||||||
|
+ if(!ttc->checkReadBytesAvailable (THRIFT_TRANSPORT (tp->transport),
|
||||||
|
+ ((gint64) lsize * thrift_protocol_get_min_serialized_size (protocol, *element_type, error)),
|
||||||
|
error))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.c
|
||||||
|
index 9d3f25e75..7e18f712a 100644
|
||||||
|
--- a/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.c
|
||||||
|
+++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.c
|
||||||
|
@@ -160,7 +160,7 @@ thrift_transport_updateKnownMessageSize(ThriftTransport *transport, glong size,
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
-thrift_transport_checkReadBytesAvailable(ThriftTransport *transport, glong numBytes, GError **error)
|
||||||
|
+thrift_transport_checkReadBytesAvailable(ThriftTransport *transport, gint64 numBytes, GError **error)
|
||||||
|
{
|
||||||
|
gboolean boolean = TRUE;
|
||||||
|
ThriftTransport *tt = THRIFT_TRANSPORT (transport);
|
||||||
|
diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.h b/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.h
|
||||||
|
index 83fb5da19..01365ba7f 100644
|
||||||
|
--- a/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.h
|
||||||
|
+++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.h
|
||||||
|
@@ -83,7 +83,7 @@ struct _ThriftTransportClass
|
||||||
|
gint32 (*read_all) (ThriftTransport *transport, gpointer buf,
|
||||||
|
guint32 len, GError **error);
|
||||||
|
gboolean (*updateKnownMessageSize) (ThriftTransport *transport, glong size, GError **error);
|
||||||
|
- gboolean (*checkReadBytesAvailable) (ThriftTransport *transport, glong numBytes, GError **error);
|
||||||
|
+ gboolean (*checkReadBytesAvailable) (ThriftTransport *transport, gint64 numBytes, GError **error);
|
||||||
|
gboolean (*resetConsumedMessageSize) (ThriftTransport *transport, glong newSize, GError **error);
|
||||||
|
gboolean (*countConsumedMessageBytes) (ThriftTransport *transport, glong numBytes, GError **error);
|
||||||
|
};
|
||||||
|
diff --git a/lib/cpp/src/thrift/protocol/TBinaryProtocol.h b/lib/cpp/src/thrift/protocol/TBinaryProtocol.h
|
||||||
|
index cba6e6948..1a7410c86 100644
|
||||||
|
--- a/lib/cpp/src/thrift/protocol/TBinaryProtocol.h
|
||||||
|
+++ b/lib/cpp/src/thrift/protocol/TBinaryProtocol.h
|
||||||
|
@@ -174,18 +174,18 @@ public:
|
||||||
|
|
||||||
|
void checkReadBytesAvailable(TSet& set) override
|
||||||
|
{
|
||||||
|
- trans_->checkReadBytesAvailable(set.size_ * getMinSerializedSize(set.elemType_));
|
||||||
|
+ trans_->checkReadBytesAvailable(static_cast<int64_t>(set.size_) * getMinSerializedSize(set.elemType_));
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkReadBytesAvailable(TList& list) override
|
||||||
|
{
|
||||||
|
- trans_->checkReadBytesAvailable(list.size_ * getMinSerializedSize(list.elemType_));
|
||||||
|
+ trans_->checkReadBytesAvailable(static_cast<int64_t>(list.size_) * getMinSerializedSize(list.elemType_));
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkReadBytesAvailable(TMap& map) override
|
||||||
|
{
|
||||||
|
int elmSize = getMinSerializedSize(map.keyType_) + getMinSerializedSize(map.valueType_);
|
||||||
|
- trans_->checkReadBytesAvailable(map.size_ * elmSize);
|
||||||
|
+ trans_->checkReadBytesAvailable(static_cast<int64_t>(map.size_) * elmSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
diff --git a/lib/cpp/src/thrift/protocol/TCompactProtocol.h b/lib/cpp/src/thrift/protocol/TCompactProtocol.h
|
||||||
|
index c7d81eea6..97ca460a7 100644
|
||||||
|
--- a/lib/cpp/src/thrift/protocol/TCompactProtocol.h
|
||||||
|
+++ b/lib/cpp/src/thrift/protocol/TCompactProtocol.h
|
||||||
|
@@ -146,18 +146,18 @@ public:
|
||||||
|
|
||||||
|
void checkReadBytesAvailable(TSet& set) override
|
||||||
|
{
|
||||||
|
- trans_->checkReadBytesAvailable(set.size_ * getMinSerializedSize(set.elemType_));
|
||||||
|
+ trans_->checkReadBytesAvailable(static_cast<int64_t>(set.size_) * getMinSerializedSize(set.elemType_));
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkReadBytesAvailable(TList& list) override
|
||||||
|
{
|
||||||
|
- trans_->checkReadBytesAvailable(list.size_ * getMinSerializedSize(list.elemType_));
|
||||||
|
+ trans_->checkReadBytesAvailable(static_cast<int64_t>(list.size_) * getMinSerializedSize(list.elemType_));
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkReadBytesAvailable(TMap& map) override
|
||||||
|
{
|
||||||
|
int elmSize = getMinSerializedSize(map.keyType_) + getMinSerializedSize(map.valueType_);
|
||||||
|
- trans_->checkReadBytesAvailable(map.size_ * elmSize);
|
||||||
|
+ trans_->checkReadBytesAvailable(static_cast<int64_t>(map.size_) * elmSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
diff --git a/lib/cpp/src/thrift/protocol/TJSONProtocol.h b/lib/cpp/src/thrift/protocol/TJSONProtocol.h
|
||||||
|
index 09eb6eab1..265b33922 100644
|
||||||
|
--- a/lib/cpp/src/thrift/protocol/TJSONProtocol.h
|
||||||
|
+++ b/lib/cpp/src/thrift/protocol/TJSONProtocol.h
|
||||||
|
@@ -253,18 +253,18 @@ public:
|
||||||
|
|
||||||
|
void checkReadBytesAvailable(TSet& set) override
|
||||||
|
{
|
||||||
|
- trans_->checkReadBytesAvailable(set.size_ * getMinSerializedSize(set.elemType_));
|
||||||
|
+ trans_->checkReadBytesAvailable(static_cast<int64_t>(set.size_) * getMinSerializedSize(set.elemType_));
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkReadBytesAvailable(TList& list) override
|
||||||
|
{
|
||||||
|
- trans_->checkReadBytesAvailable(list.size_ * getMinSerializedSize(list.elemType_));
|
||||||
|
+ trans_->checkReadBytesAvailable(static_cast<int64_t>(list.size_) * getMinSerializedSize(list.elemType_));
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkReadBytesAvailable(TMap& map) override
|
||||||
|
{
|
||||||
|
int elmSize = getMinSerializedSize(map.keyType_) + getMinSerializedSize(map.valueType_);
|
||||||
|
- trans_->checkReadBytesAvailable(map.size_ * elmSize);
|
||||||
|
+ trans_->checkReadBytesAvailable(static_cast<int64_t>(map.size_) * elmSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
class LookaheadReader {
|
||||||
|
diff --git a/lib/cpp/src/thrift/protocol/TProtocol.h b/lib/cpp/src/thrift/protocol/TProtocol.h
|
||||||
|
index 37b0db711..4eedc5e82 100644
|
||||||
|
--- a/lib/cpp/src/thrift/protocol/TProtocol.h
|
||||||
|
+++ b/lib/cpp/src/thrift/protocol/TProtocol.h
|
||||||
|
@@ -604,18 +604,18 @@ protected:
|
||||||
|
|
||||||
|
virtual void checkReadBytesAvailable(TSet& set)
|
||||||
|
{
|
||||||
|
- ptrans_->checkReadBytesAvailable(set.size_ * getMinSerializedSize(set.elemType_));
|
||||||
|
+ ptrans_->checkReadBytesAvailable(static_cast<int64_t>(set.size_) * getMinSerializedSize(set.elemType_));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void checkReadBytesAvailable(TList& list)
|
||||||
|
{
|
||||||
|
- ptrans_->checkReadBytesAvailable(list.size_ * getMinSerializedSize(list.elemType_));
|
||||||
|
+ ptrans_->checkReadBytesAvailable(static_cast<int64_t>(list.size_) * getMinSerializedSize(list.elemType_));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void checkReadBytesAvailable(TMap& map)
|
||||||
|
{
|
||||||
|
int elmSize = getMinSerializedSize(map.keyType_) + getMinSerializedSize(map.valueType_);
|
||||||
|
- ptrans_->checkReadBytesAvailable(map.size_ * elmSize);
|
||||||
|
+ ptrans_->checkReadBytesAvailable(static_cast<int64_t>(map.size_) * elmSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<TTransport> ptrans_;
|
||||||
|
diff --git a/lib/cpp/src/thrift/transport/TTransport.h b/lib/cpp/src/thrift/transport/TTransport.h
|
||||||
|
index 52b3a0a4d..1269593ac 100644
|
||||||
|
--- a/lib/cpp/src/thrift/transport/TTransport.h
|
||||||
|
+++ b/lib/cpp/src/thrift/transport/TTransport.h
|
||||||
|
@@ -23,6 +23,7 @@
|
||||||
|
#include <thrift/Thrift.h>
|
||||||
|
#include <thrift/TConfiguration.h>
|
||||||
|
#include <thrift/transport/TTransportException.h>
|
||||||
|
+#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
@@ -272,7 +273,7 @@ public:
|
||||||
|
*
|
||||||
|
* @param numBytes numBytes bytes of data
|
||||||
|
*/
|
||||||
|
- void checkReadBytesAvailable(long int numBytes)
|
||||||
|
+ void checkReadBytesAvailable(int64_t numBytes)
|
||||||
|
{
|
||||||
|
if (remainingMessageSize_ < numBytes)
|
||||||
|
throw TTransportException(TTransportException::END_OF_FILE, "MaxMessageSize reached");
|
||||||
|
diff --git a/lib/cpp/test/ThrifttReadCheckTests.cpp b/lib/cpp/test/ThrifttReadCheckTests.cpp
|
||||||
|
index 963286100..72e798bc1 100644
|
||||||
|
--- a/lib/cpp/test/ThrifttReadCheckTests.cpp
|
||||||
|
+++ b/lib/cpp/test/ThrifttReadCheckTests.cpp
|
||||||
|
@@ -243,6 +243,54 @@ BOOST_AUTO_TEST_CASE(test_tthriftcompactprotocol_read_check_pass) {
|
||||||
|
BOOST_CHECK_NO_THROW(protocol->readString(eleven));
|
||||||
|
}
|
||||||
|
|
||||||
|
+BOOST_AUTO_TEST_CASE(test_tthriftbinaryprotocol_container_size_overflow) {
|
||||||
|
+ std::shared_ptr<TConfiguration> config (new TConfiguration(1024));
|
||||||
|
+ std::shared_ptr<TMemoryBuffer> transport(new TMemoryBuffer(config));
|
||||||
|
+ std::shared_ptr<TBinaryProtocol> protocol(new TBinaryProtocol(transport));
|
||||||
|
+
|
||||||
|
+ uint32_t val = 0;
|
||||||
|
+ TType elemType = apache::thrift::protocol::T_STOP;
|
||||||
|
+ // 0x40000000 elements of min size 4 require 4 GiB; the product wraps to 0 in
|
||||||
|
+ // 32-bit math and used to slip past the MaxMessageSize check.
|
||||||
|
+ TList list(T_I32, 0x40000000);
|
||||||
|
+ protocol->writeListBegin(list.elemType_, list.size_);
|
||||||
|
+ protocol->writeListEnd();
|
||||||
|
+ BOOST_CHECK_THROW(protocol->readListBegin(elemType, val), TTransportException);
|
||||||
|
+ protocol->readListEnd();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+BOOST_AUTO_TEST_CASE(test_tthriftcompactprotocol_container_size_overflow) {
|
||||||
|
+ std::shared_ptr<TConfiguration> config (new TConfiguration(1024));
|
||||||
|
+ std::shared_ptr<TMemoryBuffer> transport(new TMemoryBuffer(config));
|
||||||
|
+ std::shared_ptr<TCompactProtocol> protocol(new TCompactProtocol(transport));
|
||||||
|
+
|
||||||
|
+ uint32_t val = 0;
|
||||||
|
+ TType elemType = apache::thrift::protocol::T_STOP;
|
||||||
|
+ // 0x10000000 elements of min size 16 (UUID) require 4 GiB; the product wraps
|
||||||
|
+ // to 0 in 32-bit math and used to slip past the MaxMessageSize check.
|
||||||
|
+ TList list(T_UUID, 0x10000000);
|
||||||
|
+ protocol->writeListBegin(list.elemType_, list.size_);
|
||||||
|
+ protocol->writeListEnd();
|
||||||
|
+ BOOST_CHECK_THROW(protocol->readListBegin(elemType, val), TTransportException);
|
||||||
|
+ protocol->readListEnd();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+BOOST_AUTO_TEST_CASE(test_tthriftjsonprotocol_container_size_overflow) {
|
||||||
|
+ std::shared_ptr<TConfiguration> config (new TConfiguration(1024));
|
||||||
|
+ std::shared_ptr<TMemoryBuffer> transport(new TMemoryBuffer(config));
|
||||||
|
+ std::shared_ptr<TJSONProtocol> protocol(new TJSONProtocol(transport));
|
||||||
|
+
|
||||||
|
+ uint32_t val = 0;
|
||||||
|
+ TType elemType = apache::thrift::protocol::T_STOP;
|
||||||
|
+ // 0x10000000 elements of min size 16 (UUID) require 4 GiB; the product wraps
|
||||||
|
+ // to 0 in 32-bit math and used to slip past the MaxMessageSize check.
|
||||||
|
+ TList list(T_UUID, 0x10000000);
|
||||||
|
+ protocol->writeListBegin(list.elemType_, list.size_);
|
||||||
|
+ protocol->writeListEnd();
|
||||||
|
+ BOOST_CHECK_THROW(protocol->readListBegin(elemType, val), TTransportException);
|
||||||
|
+ protocol->readListEnd();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
BOOST_AUTO_TEST_CASE(test_tthriftjsonprotocol_read_check_exception) {
|
||||||
|
std::shared_ptr<TConfiguration> config (new TConfiguration(MAX_MESSAGE_SIZE));
|
||||||
|
std::shared_ptr<TMemoryBuffer> transport(new TMemoryBuffer(config));
|
||||||
@@ -20,6 +20,7 @@ SRC_URI = "https://downloads.apache.org/${BPN}/${PV}/${BP}.tar.gz \
|
|||||||
file://CVE-2026-58662.patch \
|
file://CVE-2026-58662.patch \
|
||||||
file://CVE-2026-41608.patch \
|
file://CVE-2026-41608.patch \
|
||||||
file://CVE-2026-45112.patch \
|
file://CVE-2026-45112.patch \
|
||||||
|
file://CVE-2026-55969.patch \
|
||||||
"
|
"
|
||||||
SRC_URI[sha256sum] = "794a0e455787960d9f27ab92c38e34da27e8deeda7a5db0e59dc64a00df8a1e5"
|
SRC_URI[sha256sum] = "794a0e455787960d9f27ab92c38e34da27e8deeda7a5db0e59dc64a00df8a1e5"
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user