diff mbox series

gcc: Fix for CVE-2026-95619

Message ID 20261027091547.3224168-1-Hemanth.KumarMD@windriver.com
State Under Review
Headers show
Series gcc: Fix for CVE-2026-95619 | expand

Commit Message

Hemanth Kumar M D Oct. 27, 2026, 9:14 a.m. UTC
From: Sowmya Sathram <sowmyasathram12@gmail.com>

libstdc++: Ensure that aligned new detects size_t overflow

Depending on the implementation used for aligned new, the size argument
may be rounded up to a multiple of the alignment. If the size or
alignment is a huge value the rounded result could wraparound to a small
value and be successfully allocated, returning a non-null pointer that is
smaller than requested. Add size_t overflow checks so std::bad_alloc is
thrown instead. The using-directive for ::aligned_alloc is replaced with
a new __gnu_cxx::aligned_alloc function and the parameter adjustments are
moved from operator new into it, with the added overflow checks for the
aligned_alloc, _aligned_malloc (Wine) and malloc fallback paths.

References:
https://nvd.nist.gov/vuln/detail/CVE-2026-95619
https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=59d235ffa5a69231eb42e5290d52dc8c90d28b7a

Signed-off-by: Hemanth Kumar M D <Hemanth.KumarMD@windriver.com>
---
 meta/recipes-devtools/gcc/gcc-16.2.inc        |   1 +
 .../gcc/gcc/0027-CVE-2026-95619.patch         | 188 ++++++++++++++++++
 2 files changed, 189 insertions(+)
 create mode 100644 meta/recipes-devtools/gcc/gcc/0027-CVE-2026-95619.patch
diff mbox series

Patch

diff --git a/meta/recipes-devtools/gcc/gcc-16.2.inc b/meta/recipes-devtools/gcc/gcc-16.2.inc
index 3497493619..31a630ce8a 100644
--- a/meta/recipes-devtools/gcc/gcc-16.2.inc
+++ b/meta/recipes-devtools/gcc/gcc-16.2.inc
@@ -75,6 +75,7 @@  SRC_URI = "${BASEURI} \
            file://0001-mapper-localhost-might-not-be-known.patch \
            file://0001-Fix-check-for-working-assembler-gdwarf-4-option.patch \
 	   file://0026-CVE-2026-102010.patch \
+	   file://0027-CVE-2026-95619.patch \
 "
 
 UNPACKDIR = "${TMPDIR}/work-shared/gcc-${PV}-${PR}/sources"
diff --git a/meta/recipes-devtools/gcc/gcc/0027-CVE-2026-95619.patch b/meta/recipes-devtools/gcc/gcc/0027-CVE-2026-95619.patch
new file mode 100644
index 0000000000..e984344eac
--- /dev/null
+++ b/meta/recipes-devtools/gcc/gcc/0027-CVE-2026-95619.patch
@@ -0,0 +1,188 @@ 
+From 59d235ffa5a69231eb42e5290d52dc8c90d28b7a Mon Sep 17 00:00:00 2001
+From: Jonathan Wakely <jwakely@redhat.com>
+Date: Wed, 23 Sep 2026 13:15:18 +0100
+Subject: libstdc++: Ensure that aligned new detects size_t overflow
+ (CVE-2026-95619)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Depending on the implementation used for aligned new, we might need to
+round the size argument up to a multiple of the alignment. If either the
+size or the alignment is a huge value then the rounded result could
+wraparound to a small value which would then be successfully allocated
+by the underlying libc allocation function. This means that we return a
+non-null pointer but not of the requested size. Instead we should throw
+std::bad_alloc because the allocation cannot succeed.
+
+This doesn't affect most modern targets because they use the
+posix_memalign implementation, which doesn't do that rounding.
+
+On targets without posix_memalign we use C11 aligned_alloc and round
+before calling it. That rounding needs to be checked for overflow. The
+using-directive for ::aligned_alloc is replaced with a new
+__gnu_cxx::aligned_alloc function and the existing fix-ups for that path
+are moved from operator new into the new function, with added check for
+the overflow we need to fix.
+
+On *-*-mingw* we use the Windows _aligned_malloc function which
+correctly checks for overflow on Windows. But the Wine version of that
+function does not and has the same overflow problem so we need to do our
+own checks before calling it. We include a conservative 2*sizeof(void*)
+adjustment in our own overflow check.
+
+On targets without any aligned allocation function we provide our own
+__gnu_cxx::aligned_alloc in terms of malloc. This also needs an overflow
+check.
+
+libstdc++-v3/ChangeLog:
+
+	* libsupc++/new_opa.cc
+	[_GLIBCXX_HAVE_ALIGNED_ALLOC] (__gnu_cxx::aligned_alloc):
+	Replace using-directive with new function. Check for size_t
+	overflow.
+	[_GLIBCXX_HAVE__ALIGNED_MALLOC] (__gnu_cxx::aligned_alloc):
+	Check for size_t overflow.
+	(__gnu_cxx::aligned_alloc): Likewise in fallback definition.
+	(operator new) [_GLIBCXX_HAVE_ALIGNED_ALLOC]: Move parameter
+	adjustments to new __gnu_cxx::aligned_alloc function.
+	* testsuite/18_support/new_aligned_wrap.cc: New test.
+
+CVE: CVE-2026-95619
+
+Upstream-Status: Backport [https://gcc.gnu.org/cgit/gcc/patch/?id=59d235ffa5a69231eb42e5290d52dc8c90d28b7a]
+
+Reviewed-by: Tomasz KamiƄski <tkaminsk@redhat.com>
+Signed-off-by: Hemanth Kumar M D <Hemanth.KumarMD@windriver.com>
+---
+ libstdc++-v3/libsupc++/new_opa.cc                  | 49 ++++++++++++++--------
+ .../testsuite/18_support/new_aligned_wrap.cc       | 39 +++++++++++++++++
+ 2 files changed, 71 insertions(+), 17 deletions(-)
+ create mode 100644 libstdc++-v3/testsuite/18_support/new_aligned_wrap.cc
+
+diff --git a/libstdc++-v3/libsupc++/new_opa.cc b/libstdc++-v3/libsupc++/new_opa.cc
+index 7bda847a9257..bd0098ac09e4 100644
+--- a/libstdc++-v3/libsupc++/new_opa.cc
++++ b/libstdc++-v3/libsupc++/new_opa.cc
+@@ -81,12 +81,38 @@ aligned_alloc (std::size_t al, std::size_t sz)
+   return nullptr;
+ }
+ #elif _GLIBCXX_HAVE_ALIGNED_ALLOC
+-using ::aligned_alloc;
++// We have C11 aligned_alloc but we need to satisfy its preconditions.
++static inline void*
++aligned_alloc (std::size_t al, std::size_t sz)
++{
++# if defined _AIX || defined __APPLE__
++  /* AIX 7.2.0.0 aligned_alloc incorrectly has posix_memalign's requirement
++   * that alignment is a multiple of sizeof(void*).
++   * OS X 10.15 has the same requirement.  */
++  if (al < sizeof(void*))
++    al = sizeof(void*);
++# endif
++  /* C11: the value of size shall be an integral multiple of alignment.  */
++  if (__builtin_add_overflow(sz, al - 1, &sz)) [[unlikely]]
++    return nullptr;
++  sz &= ~(al - 1);
++  return ::aligned_alloc(al, sz);
++}
+ #elif _GLIBCXX_HAVE__ALIGNED_MALLOC
++// Use Windows _aligned_malloc
+ static inline void*
+ aligned_alloc (std::size_t al, std::size_t sz)
+-{ return _aligned_malloc(sz, al); }
++{
++  // The Wine msvcrt.dll version of _aligned_malloc doesn't detect overflow
++  // so do it ourselves. We know al + 2 * sizeof(void*) won't overflow because
++  // has_single_bit(al) was already checked by the caller.
++  std::size_t check;
++  if (__builtin_add_overflow(sz, al + 2 * sizeof(void*), &check)) [[unlikely]]
++    return nullptr;
++  return _aligned_malloc(sz, al);
++}
+ #elif _GLIBCXX_HAVE_MEMALIGN
++// Use memalign (and assume that what it returns can be passed to free).
+ static inline void*
+ aligned_alloc (std::size_t al, std::size_t sz)
+ {
+@@ -103,8 +129,10 @@ aligned_alloc (std::size_t al, std::size_t sz)
+   // We need extra bytes to store the original value returned by malloc.
+   if (al < sizeof(void*))
+     al = sizeof(void*);
+-  void* const malloc_ptr = malloc(sz + al);
+-  if (!malloc_ptr)
++  if (__builtin_add_overflow(sz, al, &sz)) [[unlikely]]
++    return nullptr;
++  void* const malloc_ptr = malloc(sz);
++  if (!malloc_ptr) [[unlikely]]
+     return nullptr;
+   // Align to the requested value, leaving room for the original malloc value.
+   void* const aligned_ptr = (void *) (((uintptr_t) malloc_ptr + al) & -al);
+@@ -131,19 +159,6 @@ operator new (std::size_t sz, std::align_val_t al)
+   if (__builtin_expect (sz == 0, false))
+     sz = 1;
+ 
+-#if _GLIBCXX_HAVE_POSIX_MEMALIGN
+-#elif _GLIBCXX_HAVE_ALIGNED_ALLOC
+-# if defined _AIX || defined __APPLE__
+-  /* AIX 7.2.0.0 aligned_alloc incorrectly has posix_memalign's requirement
+-   * that alignment is a multiple of sizeof(void*).
+-   * OS X 10.15 has the same requirement.  */
+-  if (align < sizeof(void*))
+-    align = sizeof(void*);
+-# endif
+-  /* C11: the value of size shall be an integral multiple of alignment.  */
+-  sz = (sz + align - 1) & ~(align - 1);
+-#endif
+-
+   void *p;
+ 
+   while ((p = __gnu_cxx::aligned_alloc (align, sz)) == nullptr)
+diff --git a/libstdc++-v3/testsuite/18_support/new_aligned_wrap.cc b/libstdc++-v3/testsuite/18_support/new_aligned_wrap.cc
+new file mode 100644
+index 000000000000..dbd642d6ba58
+--- /dev/null
++++ b/libstdc++-v3/testsuite/18_support/new_aligned_wrap.cc
+@@ -0,0 +1,39 @@
++// { dg-do run }
++
++#include <new>
++#include <stdint.h>
++#include <testsuite_hooks.h>
++
++#pragma GCC diagnostic ignored "-Walloc-size-larger-than="
++
++void
++check_aligned_new_overflow(std::size_t size, std::size_t align)
++{
++#if __cpp_aligned_new
++  std::align_val_t alignv = (std::align_val_t)align;
++  try
++    {
++      (void) ::operator new(size, alignv);
++      VERIFY(false);
++    }
++  catch (const std::bad_alloc&)
++    {
++    }
++
++  void* p = ::operator new(size, alignv, std::nothrow);
++  VERIFY(p == 0);
++#endif
++}
++
++int main()
++{
++  check_aligned_new_overflow(-9, 32);
++  check_aligned_new_overflow(SIZE_MAX, 8);
++  check_aligned_new_overflow(SIZE_MAX, 32);
++  check_aligned_new_overflow(SIZE_MAX, 1024);
++  check_aligned_new_overflow(SIZE_MAX, 65536);
++  check_aligned_new_overflow(SIZE_MAX -     1,    16);
++  check_aligned_new_overflow(SIZE_MAX -  1025,  1024);
++  check_aligned_new_overflow(SIZE_MAX -  1024,  1024);
++  check_aligned_new_overflow(SIZE_MAX - 65536, 65536);
++}
+-- 
+cgit 
+