mirror of
git://git.openembedded.org/meta-openembedded
synced 2026-11-05 23:31:22 +00:00
Backport a patch to fix CVE-2025-0838
CVE-2025-0838:
There exists a heap buffer overflow vulnerable in Abseil-cpp. The sized
constructors, reserve(), and rehash() methods of
absl::{flat,node}hash{set,map} did not impose an upper bound on their
size argument. As a result, it was possible for a caller to pass a very
large size that would cause an integer overflow when computing the size
of the container's backing store, and a subsequent out-of-bounds memory
write. Subsequent accesses to the container might also access
out-of-bounds memory. We recommend upgrading past commit
5a0e2cb5e3958dd90bb8569a2766622cb74d90c1
Reference:
https://nvd.nist.gov/vuln/detail/CVE-2025-0838
Signed-off-by: Changqing Li <changqing.li@windriver.com>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
115 lines
4.4 KiB
Diff
115 lines
4.4 KiB
Diff
From bdbad523d92cd2308139086226bfc36fc2068267 Mon Sep 17 00:00:00 2001
|
|
From: Changqing Li <changqing.li@windriver.com>
|
|
Date: Thu, 27 Feb 2025 12:05:11 +0800
|
|
Subject: [PATCH] Fix potential integer overflow in hash container
|
|
create/resize (#1813)
|
|
|
|
The sized constructors, reserve(), and rehash() methods of
|
|
absl::{flat,node}_hash_{set,map} did not impose an upper bound on
|
|
their size argument. As a result, it was possible for a caller to pass
|
|
a very large size that would cause an integer overflow when computing
|
|
the size of the container's backing store. Subsequent accesses to the
|
|
container might then access out-of-bounds memory.
|
|
|
|
The fix is in two parts:
|
|
|
|
1) Update max_size() to return the maximum number of items that can be
|
|
stored in the container
|
|
|
|
2) Validate the size arguments to the constructors, reserve(), and
|
|
rehash() methods, and abort the program when the argument is invalid
|
|
|
|
We've looked at uses of these containers in Google codebases like
|
|
Chrome, and determined this vulnerability is likely to be difficult to
|
|
exploit. This is primarily because container sizes are rarely
|
|
attacker-controlled.
|
|
|
|
The bug was discovered by Dmitry Vyukov <dvyukov@google.com>.
|
|
|
|
CVE: CVE-2025-0838
|
|
Upstream-Status: Backport [https://github.com/abseil/abseil-cpp/commit/caa7bb4457bfcafcd55a940204ef78c1bf1f417d]
|
|
This patch is backported from 20230802.3
|
|
|
|
Signed-off-by: Changqing Li <changqing.li@windriver.com>
|
|
---
|
|
absl/container/internal/raw_hash_set.h | 15 ++++++++++++++-
|
|
absl/container/internal/raw_hash_set_test.cc | 8 ++++++++
|
|
2 files changed, 22 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h
|
|
index 046a6939..ecea25b4 100644
|
|
--- a/absl/container/internal/raw_hash_set.h
|
|
+++ b/absl/container/internal/raw_hash_set.h
|
|
@@ -662,6 +662,12 @@ inline size_t NormalizeCapacity(size_t n) {
|
|
return n ? ~size_t{} >> countl_zero(n) : 1;
|
|
}
|
|
|
|
+template <size_t kSlotSize>
|
|
+size_t MaxValidCapacity() {
|
|
+ return NormalizeCapacity((std::numeric_limits<size_t>::max)() / 4 /
|
|
+ kSlotSize);
|
|
+}
|
|
+
|
|
// General notes on capacity/growth methods below:
|
|
// - We use 7/8th as maximum load factor. For 16-wide groups, that gives an
|
|
// average of two empty slots per group.
|
|
@@ -1065,6 +1071,8 @@ class raw_hash_set {
|
|
: ctrl_(EmptyGroup()),
|
|
settings_(0, HashtablezInfoHandle(), hash, eq, alloc) {
|
|
if (bucket_count) {
|
|
+ ABSL_RAW_CHECK(bucket_count <= MaxValidCapacity<sizeof(slot_type)>(),
|
|
+ "Hash table size overflow");
|
|
capacity_ = NormalizeCapacity(bucket_count);
|
|
initialize_slots();
|
|
}
|
|
@@ -1258,7 +1266,9 @@ class raw_hash_set {
|
|
bool empty() const { return !size(); }
|
|
size_t size() const { return size_; }
|
|
size_t capacity() const { return capacity_; }
|
|
- size_t max_size() const { return (std::numeric_limits<size_t>::max)(); }
|
|
+ size_t max_size() const {
|
|
+ return CapacityToGrowth(MaxValidCapacity<sizeof(slot_type)>());
|
|
+ }
|
|
|
|
ABSL_ATTRIBUTE_REINITIALIZES void clear() {
|
|
// Iterating over this container is O(bucket_count()). When bucket_count()
|
|
@@ -1595,6 +1605,8 @@ class raw_hash_set {
|
|
auto m = NormalizeCapacity(n | GrowthToLowerboundCapacity(size()));
|
|
// n == 0 unconditionally rehashes as per the standard.
|
|
if (n == 0 || m > capacity_) {
|
|
+ ABSL_RAW_CHECK(m <= MaxValidCapacity<sizeof(slot_type)>(),
|
|
+ "Hash table size overflow");
|
|
resize(m);
|
|
|
|
// This is after resize, to ensure that we have completed the allocation
|
|
@@ -1605,6 +1617,7 @@ class raw_hash_set {
|
|
|
|
void reserve(size_t n) {
|
|
if (n > size() + growth_left()) {
|
|
+ ABSL_RAW_CHECK(n <= max_size(), "Hash table size overflow");
|
|
size_t m = GrowthToLowerboundCapacity(n);
|
|
resize(NormalizeCapacity(m));
|
|
|
|
diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc
|
|
index 9cd88a28..81a5c866 100644
|
|
--- a/absl/container/internal/raw_hash_set_test.cc
|
|
+++ b/absl/container/internal/raw_hash_set_test.cc
|
|
@@ -2176,6 +2176,14 @@ TEST(Table, AlignOne) {
|
|
}
|
|
}
|
|
|
|
+TEST(Table, MaxSizeOverflow) {
|
|
+ size_t overflow = (std::numeric_limits<size_t>::max)();
|
|
+ EXPECT_DEATH_IF_SUPPORTED(IntTable t(overflow), "Hash table size overflow");
|
|
+ IntTable t;
|
|
+ EXPECT_DEATH_IF_SUPPORTED(t.reserve(overflow), "Hash table size overflow");
|
|
+ EXPECT_DEATH_IF_SUPPORTED(t.rehash(overflow), "Hash table size overflow");
|
|
+}
|
|
+
|
|
} // namespace
|
|
} // namespace container_internal
|
|
ABSL_NAMESPACE_END
|
|
--
|
|
2.34.1
|
|
|