From: Michael Tremer Date: Mon, 19 Jan 2026 11:05:15 +0000 (+0000) Subject: glibc: Add fixes for CVE-2026-0861 and CVE-2026-0915 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bf11ee44f03f4ed68b17f35be71ddfeb85391f7b;p=ipfire-2.x.git glibc: Add fixes for CVE-2026-0861 and CVE-2026-0915 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 --- diff --git a/lfs/glibc b/lfs/glibc index 7bba2b60b..32dcdb386 100644 --- 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 index 000000000..5126d2e25 --- /dev/null +++ b/src/patches/glibc-2.42-CVE-2026-0861.patch @@ -0,0 +1,88 @@ +From b0ec8fb689df862171f0f78994a3bdeb51313545 Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar +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 +Signed-off-by: Siddhesh Poyarekar +(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 index 000000000..078dc451f --- /dev/null +++ b/src/patches/glibc-2.42-CVE-2026-0915.patch @@ -0,0 +1,77 @@ +From 453e6b8dbab935257eb0802b0c97bca6b67ba30e Mon Sep 17 00:00:00 2001 +From: Carlos O'Donell +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 +(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 +