]> git.ipfire.org Git - ipfire-2.x.git/commitdiff
glibc: Add fixes for CVE-2026-0861 and CVE-2026-0915
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 19 Jan 2026 11:05:15 +0000 (11:05 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 19 Jan 2026 11:05:15 +0000 (11:05 +0000)
GLIBC-SA-2026-0001:
===================

Integer overflow in memalign leads to heap corruption

Passing too large an alignment to the memalign suite of functions
(memalign, posix_memalign, aligned_alloc) in the GNU C Library version
2.30 to 2.42 may result in an integer overflow, which could consequently
result in a heap corruption.

Note that the attacker must have control over both, the size as well as
the alignment arguments of the memalign function to be able to exploit
this.  The size parameter must be close enough to PTRDIFF_MAX so as to
overflow size_t along with the large alignment argument.  This limits
the malicious inputs for the alignment for memalign to the range [1<<62
+ 1, 1<<63] and exactly 1<<63 for posix_memalign and aligned_alloc.

Typically the alignment argument passed to such functions is a known
constrained quantity (e.g. page size, block size, struct sizes) and is
not attacker controlled, because of which this may not be easily
exploitable in practice.  An application bug could potentially result in
the input alignment being too large, e.g. due to a different buffer
overflow or integer overflow in the application or its dependent
libraries, but that is again an uncommon usage pattern given typical
sources of alignments.

CVE-Id: CVE-2026-0861
Public-Date: 2026-01-14
Vulnerable-Commit: 9bf8e29ca136094f73f69f725f15c51facc97206 (2.30)
Fix-Commit: c9188d333717d3ceb7e3020011651f424f749f93 (2.43)
Fix-Commit: 7f19ef14fbce095d4c77395e258320cad2ea2b28 (2.30-153)
Fix-Commit: f18446d7b4a423090ee5e328c36b3c2a0f26041c (2.31-166)
Fix-Commit: 8aef9e7a7af9565c0324b4ecb38b30dfa3782fd8 (2.32-151)
Fix-Commit: 011293b4fd748cdd6f95874ba2b6aba9a3df8bff (2.33-275)
Fix-Commit: 2c77e52108a58956c9f674b36e1f59a4e3fdcf4d (2.34-525)
Fix-Commit: 499d1ccafccfe64df1b88deea2fa84d8180e8e8f (2.35-399)
Fix-Commit: fb6b8822175769b5794fb6ea04f2895483a29b61 (2.36-244)
Fix-Commit: 7b913d41a07836def826f2164c52541a9835f324 (2.37-172)
Fix-Commit: 744b63026a29f7eedbbc8e3a01a7f48a6eb0a085 (2.38-212)
Fix-Commit: fb22fd3f5b415dd4cd6f7b5741c2f0412374e242 (2.39-286)
Fix-Commit: bfc4dd9e526eacf3017dd8864ba0848e9d045dd4 (2.40-216)
Fix-Commit: 1e2c1ea4307197ccece0cda574bcfebf9080894c (2.41-121)
Fix-Commit: b0ec8fb689df862171f0f78994a3bdeb51313545 (2.42-49)
Reported-by: Igor Morgenstern, Aisle Research
GLIBC-SA-2026-0002:
===================
getnetbyaddr and getnetbyaddr_r leak stack contents to DNS resovler

Calling getnetbyaddr or getnetbyaddr_r with a configured nsswitch.conf
that specifies the library's DNS backend for networks and queries for a
zero-valued network in the GNU C Library version 2.0 to version 2.42
can leak stack contents to the configured DNS resolver.

A defect in the _nss_dns_getnetbyaddr_r function which implements
getnetbyaddr and getnetbyaddr_r in the dns-based network database can
pass stack contents unmodified to the configured DNS resolver as part of
the network DNS query when the network queried is the default network
i.e. net == 0x0.  This stack contents leaking in the query is considered
a loss of confidentiality for the host making the query.  Typically it
is rare to call these APIs with a net value of zero, and if an attacker
can control the net value it can only leak adjacent stack, and so loss
of confidentiality is spatially limited.  The leak might be used to
accelerate an ASLR bypass by knowing pointer values, but also requires
network adjacent access to snoop between the application and the
DNS server; making the attack complexity higher.

CVE-Id: CVE-2026-0915
Public-Date: 2026-01-15
Vulnerable-Commit: 5f0e6fc702296840d2daa39f83f6cb1e40073d58 (1.92-1)
Fix-Commit: e56ff82d5034ec66c6a78f517af6faa427f65b0b (2.43)
Reported-by: Igor Morgenstern, Aisle Research
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
lfs/glibc
src/patches/glibc-2.42-CVE-2026-0861.patch [new file with mode: 0644]
src/patches/glibc-2.42-CVE-2026-0915.patch [new file with mode: 0644]

index 7bba2b60b8e1c4620e5c7f81dca586a51f81d0b3..32dcdb3860ec2a509abad26cf8449ec5da951cd5 100644 (file)
--- a/lfs/glibc
+++ b/lfs/glibc
@@ -120,6 +120,8 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
        @mkdir $(DIR_SRC)/glibc-build
 
        cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc-localedef-no-archive.patch
+       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc-2.42-CVE-2026-0861.patch
+       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc-2.42-CVE-2026-0915.patch
 
 ifneq "$(TOOLCHAIN)" "1"
  ifeq "$(BUILD_ARCH)" "x86_64"
diff --git a/src/patches/glibc-2.42-CVE-2026-0861.patch b/src/patches/glibc-2.42-CVE-2026-0861.patch
new file mode 100644 (file)
index 0000000..5126d2e
--- /dev/null
@@ -0,0 +1,88 @@
+From b0ec8fb689df862171f0f78994a3bdeb51313545 Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@gotplt.org>
+Date: Thu, 15 Jan 2026 06:06:40 -0500
+Subject: [PATCH] memalign: reinstate alignment overflow check (CVE-2026-0861)
+
+The change to cap valid sizes to PTRDIFF_MAX inadvertently dropped the
+overflow check for alignment in memalign functions, _mid_memalign and
+_int_memalign.  Reinstate the overflow check in _int_memalign, aligned
+with the PTRDIFF_MAX change since that is directly responsible for the
+CVE.  The missing _mid_memalign check is not relevant (and does not have
+a security impact) and may need a different approach to fully resolve,
+so it has been omitted.
+
+CVE-Id: CVE-2026-0861
+Vulnerable-Commit: 9bf8e29ca136094f73f69f725f15c51facc97206
+Reported-by: Igor Morgenstern, Aisle Research
+Fixes: BZ #33796
+Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
+Signed-off-by: Siddhesh Poyarekar <siddhesh@gotplt.org>
+(cherry picked from commit c9188d333717d3ceb7e3020011651f424f749f93)
+---
+ malloc/malloc.c               |  7 +++++--
+ malloc/tst-malloc-too-large.c | 10 ++--------
+ 2 files changed, 7 insertions(+), 10 deletions(-)
+
+diff --git a/malloc/malloc.c b/malloc/malloc.c
+index 5f3e701fd1..1d5aa304d3 100644
+--- a/malloc/malloc.c
++++ b/malloc/malloc.c
+@@ -5167,7 +5167,7 @@ _int_memalign (mstate av, size_t alignment, size_t bytes)
+   INTERNAL_SIZE_T size;
+   nb = checked_request2size (bytes);
+-  if (nb == 0)
++  if (nb == 0 || alignment > PTRDIFF_MAX)
+     {
+       __set_errno (ENOMEM);
+       return NULL;
+@@ -5183,7 +5183,10 @@ _int_memalign (mstate av, size_t alignment, size_t bytes)
+      we don't find anything in those bins, the common malloc code will
+      scan starting at 2x.  */
+-  /* Call malloc with worst case padding to hit alignment. */
++  /* Call malloc with worst case padding to hit alignment.  ALIGNMENT is a
++     power of 2, so it tops out at (PTRDIFF_MAX >> 1) + 1, leaving plenty of
++     space to add MINSIZE and whatever checked_request2size adds to BYTES to
++     get NB.  Consequently, total below also does not overflow.  */
+   m = (char *) (_int_malloc (av, nb + alignment + MINSIZE));
+   if (m == NULL)
+diff --git a/malloc/tst-malloc-too-large.c b/malloc/tst-malloc-too-large.c
+index a548a37b46..a1bda673a3 100644
+--- a/malloc/tst-malloc-too-large.c
++++ b/malloc/tst-malloc-too-large.c
+@@ -152,7 +152,6 @@ test_large_allocations (size_t size)
+ }
+-static long pagesize;
+ /* This function tests the following aligned memory allocation functions
+    using several valid alignments and precedes each allocation test with a
+@@ -171,8 +170,8 @@ test_large_aligned_allocations (size_t size)
+   /* All aligned memory allocation functions expect an alignment that is a
+      power of 2.  Given this, we test each of them with every valid
+-     alignment from 1 thru PAGESIZE.  */
+-  for (align = 1; align <= pagesize; align *= 2)
++     alignment for the type of ALIGN, i.e. until it wraps to 0.  */
++  for (align = 1; align > 0; align <<= 1)
+     {
+       test_setup ();
+ #if __GNUC_PREREQ (7, 0)
+@@ -265,11 +264,6 @@ do_test (void)
+   DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
+ #endif
+-  /* Aligned memory allocation functions need to be tested up to alignment
+-     size equivalent to page size, which should be a power of 2.  */
+-  pagesize = sysconf (_SC_PAGESIZE);
+-  TEST_VERIFY_EXIT (powerof2 (pagesize));
+-
+   /* Loop 1: Ensure that all allocations with SIZE close to SIZE_MAX, i.e.
+      in the range (SIZE_MAX - 2^14, SIZE_MAX], fail.
+-- 
+2.47.3
+
diff --git a/src/patches/glibc-2.42-CVE-2026-0915.patch b/src/patches/glibc-2.42-CVE-2026-0915.patch
new file mode 100644 (file)
index 0000000..078dc45
--- /dev/null
@@ -0,0 +1,77 @@
+From 453e6b8dbab935257eb0802b0c97bca6b67ba30e Mon Sep 17 00:00:00 2001
+From: Carlos O'Donell <carlos@redhat.com>
+Date: Thu, 15 Jan 2026 15:09:38 -0500
+Subject: [PATCH] resolv: Fix NSS DNS backend for getnetbyaddr (CVE-2026-0915)
+
+The default network value of zero for net was never tested for and
+results in a DNS query constructed from uninitialized stack bytes.
+The solution is to provide a default query for the case where net
+is zero.
+
+Adding a test case for this was straight forward given the existence of
+tst-resolv-network and if the test is added without the fix you observe
+this failure:
+
+FAIL: resolv/tst-resolv-network
+original exit status 1
+error: tst-resolv-network.c:174: invalid QNAME: \146\218\129\128
+error: 1 test failures
+
+With a random QNAME resulting from the use of uninitialized stack bytes.
+
+After the fix the test passes.
+
+Additionally verified using wireshark before and after to ensure
+on-the-wire bytes for the DNS query were as expected.
+
+No regressions on x86_64.
+
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+(cherry picked from commit e56ff82d5034ec66c6a78f517af6faa427f65b0b)
+---
+ resolv/nss_dns/dns-network.c | 4 ++++
+ resolv/tst-resolv-network.c  | 6 ++++++
+ 2 files changed, 10 insertions(+)
+
+diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c
+index 519f8422ca..e14e959d7c 100644
+--- a/resolv/nss_dns/dns-network.c
++++ b/resolv/nss_dns/dns-network.c
+@@ -207,6 +207,10 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result,
+       sprintf (qbuf, "%u.%u.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2],
+              net_bytes[1], net_bytes[0]);
+       break;
++    default:
++      /* Default network (net is originally zero).  */
++      strcpy (qbuf, "0.0.0.0.in-addr.arpa");
++      break;
+     }
+   net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
+diff --git a/resolv/tst-resolv-network.c b/resolv/tst-resolv-network.c
+index d9f69649d0..181be80835 100644
+--- a/resolv/tst-resolv-network.c
++++ b/resolv/tst-resolv-network.c
+@@ -46,6 +46,9 @@ handle_code (const struct resolv_response_context *ctx,
+ {
+   switch (code)
+     {
++    case 0:
++      send_ptr (b, qname, qclass, qtype, "0.in-addr.arpa");
++      break;
+     case 1:
+       send_ptr (b, qname, qclass, qtype, "1.in-addr.arpa");
+       break;
+@@ -265,6 +268,9 @@ do_test (void)
+                 "error: TRY_AGAIN\n");
+   /* Lookup by address, success cases.  */
++  check_reverse (0,
++                 "name: 0.in-addr.arpa\n"
++                 "net: 0x00000000\n");
+   check_reverse (1,
+                  "name: 1.in-addr.arpa\n"
+                  "net: 0x00000001\n");
+-- 
+2.47.3
+