Overwrite target for x86_64_v2

Update patch-git.lua to handle AlmaLinux branches correctly
This commit is contained in:
Eduard Abdullin 2026-04-03 01:34:37 +00:00 committed by root
commit 9e9c50d8ae
8 changed files with 1051 additions and 1 deletions

View File

@ -0,0 +1,287 @@
commit 60b039bf6afe7f124e1d4fd3ec3bef2d745d567c
Author: Sergey Kolosov <skolosov@redhat.com>
Date: Tue Jun 25 11:19:03 2024 +0200
socket: Add new test for shutdown
This commit adds shutdown test with SHUT_RD, SHUT_WR, SHUT_RDWR for an
UNIX socket connection.
Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit 50f5a09e68e0c4ea60f5dfee3cc6963df2762e14)
diff --git a/socket/Makefile b/socket/Makefile
index fc1bd0a2608f04bc..df732fa9b72570cd 100644
--- a/socket/Makefile
+++ b/socket/Makefile
@@ -71,6 +71,7 @@ tests := \
tst-cmsg_cloexec \
tst-cmsghdr \
tst-connect \
+ tst-shutdown \
tst-sockopt \
# tests
diff --git a/socket/tst-shutdown.c b/socket/tst-shutdown.c
new file mode 100644
index 0000000000000000..a305e5e494cc38f1
--- /dev/null
+++ b/socket/tst-shutdown.c
@@ -0,0 +1,257 @@
+/* Test the shutdown function.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/xsocket.h>
+#include <support/xunistd.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+
+struct connection
+{
+ int sockets[2];
+};
+
+void
+establish_connection (struct connection *conn)
+{
+ if (socketpair (AF_UNIX, SOCK_STREAM, 0, conn->sockets) != 0)
+ {
+ FAIL_EXIT1 ("socketpair (AF_UNIX, SOCK_STREAM, 0): %m\n");
+ }
+}
+
+void
+close_connection (struct connection *conn)
+{
+ xclose (conn->sockets[0]);
+ xclose (conn->sockets[1]);
+}
+
+/* Open a file and check that shutdown fails with the ENOTSOCK error code. */
+void
+do_test_enotsock (void)
+{
+ /* Open file and check that shutdown will fail with ENOTSOCK. */
+ int fd = xopen ("/dev/null", O_RDWR, 0);
+
+ int result = shutdown (fd, SHUT_RD);
+ if (result == 0 || errno != ENOTSOCK)
+ {
+ FAIL_EXIT1 ("shutdown should fail with ENOTSOCK");
+ }
+ xclose (fd);
+}
+
+/* Test shutdown with SHUT_RD. */
+void
+do_test_shut_rd (void)
+{
+ struct connection conn;
+ const char *str = "AAAAAAA";
+ int len = 8;
+ int ret;
+ void *s_buf = xmalloc (len);
+ bzero (s_buf, len);
+
+ establish_connection (&conn);
+ int server = conn.sockets[0];
+ int client = conn.sockets[1];
+
+ /* Call shutdown with SHUT_RD on server socket. */
+ if (shutdown (server, SHUT_RD) != 0)
+ {
+ FAIL_EXIT1 ("shutdown with SHUT_RD on socket %d failed", server);
+ }
+
+ ret = send (server, str, len, 0);
+ if (ret <= 0)
+ {
+ FAIL_EXIT1 ("send (%d, data, %d): %m", server, len);
+ }
+
+ ret = recv (client, s_buf, len, 0);
+ if (ret <= 0)
+ {
+ FAIL_EXIT1 ("recv (%d, data, %d): %m", client, len);
+ }
+
+ TEST_COMPARE_BLOB (str, len, s_buf, len);
+
+ /* Send data should be disallowed on shutdown socket. */
+ errno = 0;
+ ret = send (client, str, len, MSG_NOSIGNAL);
+ if (ret >= 0 || errno != EPIPE)
+ {
+ FAIL_EXIT1 ("Send on SHUT_RD socket should be disallowed: %m");
+ }
+
+ /* Recv should return zero and no error. */
+ errno = 0;
+ ret = recv (server, s_buf, len, 0);
+ if (ret != 0 || errno != 0)
+ {
+ FAIL_EXIT1 ("recv should return 0 without error: %m");
+ }
+
+ close_connection (&conn);
+}
+
+/* Test shutdown with SHUT_WR. */
+void
+do_test_shut_wr (void)
+{
+ struct connection conn;
+ const char *str1 = "CCCCCCC";
+ const char *str2 = "DDDDDDD";
+ const char *str3 = "EEEEEEE";
+ int len = 8;
+ int ret;
+ void *c_buf = xmalloc (len);
+ void *s_buf = xmalloc (len);
+
+ establish_connection (&conn);
+ int server = conn.sockets[0];
+ int client = conn.sockets[1];
+
+ xwrite (client, str1, len);
+
+ if (shutdown (client, SHUT_WR) != 0)
+ {
+ FAIL_EXIT1 ("shutdown with SHUT_WR on socket %d failed", client);
+ }
+
+ ret = send (client, str2, len, MSG_NOSIGNAL);
+ if (ret >= 0)
+ {
+ FAIL_EXIT1 ("send on SHUT_WR socket should fail");
+ }
+
+ /* Read data written before shutdown and check if it's correct. */
+ xread (server, s_buf, len);
+ TEST_COMPARE_BLOB (str1, len, s_buf, len);
+
+ /* Second read should return zero without error. */
+ errno = 0;
+ if (read (server, s_buf, len) != 0 || errno != 0)
+ {
+ FAIL_EXIT1 ("read after shutdown should return zero without error: %m");
+ }
+
+ /* Write some data to socket and check it still can be read on other side. */
+ memcpy (s_buf, str3, len);
+ xwrite (server, s_buf, len);
+
+ xread (client, c_buf, len);
+ TEST_COMPARE_BLOB (s_buf, len, c_buf, len);
+
+ close_connection (&conn);
+}
+
+/* Test shutdown with SHUT_RDWR. */
+void
+do_test_shut_rdwr (void)
+{
+ struct connection conn;
+ struct sockaddr peer;
+ socklen_t peer_len = sizeof (peer);
+
+ const char *str1 = "FFFFFFF";
+ const char *str2 = "GGGGGGG";
+ int len = 8;
+ int ret;
+ void *s_buf = xmalloc (len);
+ bzero (s_buf, len);
+
+ establish_connection (&conn);
+ int server = conn.sockets[0];
+ int client = conn.sockets[1];
+
+ /* Send some data to both sockets before shutdown. */
+ xwrite (client, str1, len);
+ xwrite (server, str2, len);
+
+ /* Call shutdown with SHUT_RDWR on client socket. */
+ if (shutdown (client, SHUT_RDWR) != 0)
+ {
+ FAIL_EXIT1 ("shutdown with SHUT_RDWR on socket %d failed", client);
+ }
+
+ /* Verify that socket is still connected. */
+ xgetsockname (client, &peer, &peer_len);
+
+ /* Read data written before shutdown. */
+ xread (client, s_buf, len);
+ TEST_COMPARE_BLOB (s_buf, len, str2, len);
+
+ /* Second read should return zero, but no error. */
+ errno = 0;
+ if (read (client, s_buf, len) != 0 || errno != 0)
+ {
+ FAIL_EXIT1 ("read after shutdown should return zero without error: %m");
+ }
+
+ /* Send some data to shutdown socket and expect error. */
+ errno = 0;
+ ret = send (server, str2, len, MSG_NOSIGNAL);
+ if (ret >= 0 || errno != EPIPE)
+ {
+ FAIL_EXIT1 ("send to RDWR shutdown socket should fail with EPIPE");
+ }
+
+ /* Read data written before shutdown. */
+ xread (server, s_buf, len);
+ TEST_COMPARE_BLOB (s_buf, len, str1, len);
+
+ /* Second read should return zero, but no error. */
+ errno = 0;
+ if (read (server, s_buf, len) != 0 || errno != 0)
+ {
+ FAIL_EXIT1 ("read after shutdown should return zero without error: %m");
+ }
+
+ /* Send some data to shutdown socket and expect error. */
+ errno = 0;
+ ret = send (client, str1, len, MSG_NOSIGNAL);
+ if (ret >= 0 || errno != EPIPE)
+ {
+ FAIL_EXIT1 ("send to RDWR shutdown socket should fail with EPIPE");
+ }
+
+ close_connection (&conn);
+}
+
+static int
+do_test (void)
+{
+ do_test_enotsock ();
+ do_test_shut_rd ();
+ do_test_shut_wr ();
+ do_test_shut_rdwr ();
+
+ return 0;
+}
+
+#include <support/test-driver.c>

View File

@ -0,0 +1,36 @@
commit ba29a36aa32caa03a49d8b3116baecac6a5754ed
Author: Yury Khrustalev <yury.khrustalev@arm.com>
Date: Thu Nov 6 12:57:58 2025 +0000
posix: Fix invalid flags test for p{write,read}v2
Two tests fail from time to time when a new flag is added for the
p{write,read}v2 functions in a new Linux kernel:
- misc/tst-preadvwritev2
- misc/tst-preadvwritev64v2
This disrupts when testing Glibc on a system with a newer kernel
and it seems we can try improve testing for invalid flags setting
all the bits that are not supposed to be supported (rather than
setting only the next unsupported bit).
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 58a31b4316f1f687184eb147ffa1c676bc6a190e)
diff --git a/misc/tst-preadvwritev2-common.c b/misc/tst-preadvwritev2-common.c
index 4556421a4394f3a1..ec990491330377c3 100644
--- a/misc/tst-preadvwritev2-common.c
+++ b/misc/tst-preadvwritev2-common.c
@@ -109,9 +109,8 @@ do_test_with_invalid_iov (void)
static void
do_test_with_invalid_flags (void)
{
- /* Set the next bit from the mask of all supported flags. */
- int invalid_flag = RWF_SUPPORTED != 0 ? __builtin_clz (RWF_SUPPORTED) : 2;
- invalid_flag = 0x1 << ((sizeof (int) * CHAR_BIT) - invalid_flag);
+ /* Set all the bits that are not used by the supported flags. */
+ int invalid_flag = ~RWF_SUPPORTED;
char buf[32];
const struct iovec vec = { .iov_base = buf, .iov_len = sizeof (buf) };

View File

@ -0,0 +1,25 @@
commit 2760e4c5ed7ed142e126ab165dd953619e70df28
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Nov 28 11:46:09 2025 +0100
iconvdata: Fix invalid pointer arithmetic in ANSI_X3.110 module
The expression inptr + 1 can technically be invalid: if inptr == inend,
inptr may point one element past the end of an array.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit e98bd0c54d5e296ad1be91b6fe35260c6b87e733)
diff --git a/iconvdata/ansi_x3.110.c b/iconvdata/ansi_x3.110.c
index 869cdf654087185f..44bd12a863ae8f54 100644
--- a/iconvdata/ansi_x3.110.c
+++ b/iconvdata/ansi_x3.110.c
@@ -407,7 +407,7 @@ static const char from_ucs4[][2] =
is also available. */ \
uint32_t ch2; \
\
- if (inptr + 1 >= inend) \
+ if (inend - inptr <= 1) \
{ \
/* The second character is not available. */ \
result = __GCONV_INCOMPLETE_INPUT; \

View File

@ -0,0 +1,27 @@
commit c53cd6e738ad627a2c5a18dad697d2accf7b5fd2
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon Jan 26 17:12:37 2026 +0100
posix: Run tst-wordexp-reuse-mem test
The test was not properly scheduled for execution with a Makefile
dependency.
Fixes commit 80cc58ea2de214f85b0a1d902a3b668ad2ecb302 ("posix: Reset
wordexp_t fields with WRDE_REUSE (CVE-2025-15281 / BZ 33814").
(cherry picked from commit bed2db02f3183e93f21d506786c5f884a1dec9e7)
diff --git a/posix/Makefile b/posix/Makefile
index 6dc240a5bf9f3046..443b1ed10bd4d564 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -493,7 +493,7 @@ tests-special += \
$(objpfx)tst-pcre-mem.out \
$(objpfx)tst-rxspencer-no-utf8-mem.out \
$(objpfx)tst-vfork3-mem.out \
- $(objpfx)tst-wordexp-reuse.out \
+ $(objpfx)tst-wordexp-reuse-mem.out \
# tests-special
endif
endif

View File

@ -0,0 +1,234 @@
commit 5663ab0b833df187b15e7bb4b18173e22beb8bd1
Author: Carlos O'Donell <carlos@redhat.com>
Date: Fri Mar 20 16:43:33 2026 -0400
resolv: Count records correctly (CVE-2026-4437)
The answer section boundary was previously ignored, and the code in
getanswer_ptr would iterate past the last resource record, but not
beyond the end of the returned data. This could lead to subsequent data
being interpreted as answer records, thus violating the DNS
specification. Such resource records could be maliciously crafted and
hidden from other tooling, but processed by the glibc stub resolver and
acted upon by the application. While we trust the data returned by the
configured recursive resolvers, we should not trust its format and
should validate it as required. It is a security issue to incorrectly
process the DNS protocol.
A regression test is added for response section crossing.
No regressions on x86_64-linux-gnu.
Reviewed-by: Collin Funk <collin.funk1@gmail.com>
(cherry picked from commit 9f5f18aab40ec6b61fa49a007615e6077e9a979b)
diff --git a/resolv/Makefile b/resolv/Makefile
index 05fb04edf1082690..8dba948b632d3abc 100644
--- a/resolv/Makefile
+++ b/resolv/Makefile
@@ -104,6 +104,7 @@ tests += \
tst-resolv-basic \
tst-resolv-binary \
tst-resolv-byaddr \
+ tst-resolv-dns-section \
tst-resolv-edns \
tst-resolv-invalid-cname \
tst-resolv-network \
@@ -115,6 +116,7 @@ tests += \
tst-resolv-semi-failure \
tst-resolv-short-response \
tst-resolv-trailing \
+ # tests
# This test calls __res_context_send directly, which is not exported
# from libresolv.
@@ -292,6 +294,8 @@ $(objpfx)tst-resolv-aliases: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-basic: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-binary: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-byaddr: $(objpfx)libresolv.so $(shared-thread-library)
+$(objpfx)tst-resolv-dns-section: $(objpfx)libresolv.so \
+ $(shared-thread-library)
$(objpfx)tst-resolv-edns: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-network: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-res_init: $(objpfx)libresolv.so
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index 95a7b3f0e5b6855a..74a7c08d0f055d6e 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -820,7 +820,7 @@ getanswer_ptr (unsigned char *packet, size_t packetlen,
/* expected_name may be updated to point into this buffer. */
unsigned char name_buffer[NS_MAXCDNAME];
- while (ancount > 0)
+ for (; ancount > 0; --ancount)
{
struct ns_rr_wire rr;
if (!__ns_rr_cursor_next (&c, &rr))
diff --git a/resolv/tst-resolv-dns-section.c b/resolv/tst-resolv-dns-section.c
new file mode 100644
index 0000000000000000..1171baef51e3cc36
--- /dev/null
+++ b/resolv/tst-resolv-dns-section.c
@@ -0,0 +1,162 @@
+/* Test handling of invalid section transitions (bug 34014).
+ Copyright (C) 2022-2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <array_length.h>
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/format_nss.h>
+#include <support/resolv_test.h>
+#include <support/support.h>
+
+/* Name of test, and the second section type. */
+struct item {
+ const char *test;
+ int ns_section;
+};
+
+static const struct item test_items[] =
+ {
+ { "Test crossing from ns_s_an to ns_s_ar.", ns_s_ar },
+ { "Test crossing from ns_s_an to ns_s_an.", ns_s_ns },
+
+ { NULL, 0 },
+ };
+
+/* The response is designed to contain the following:
+ - An Answer section with one T_PTR record that is skipped.
+ - A second section with a semantically invalid T_PTR record.
+ The original defect is that the response parsing would cross
+ section boundaries and handle the additional section T_PTR
+ as if it were an answer. A conforming implementation would
+ stop as soon as it reaches the end of the section. */
+static void
+response (const struct resolv_response_context *ctx,
+ struct resolv_response_builder *b,
+ const char *qname, uint16_t qclass, uint16_t qtype)
+{
+ TEST_COMPARE (qclass, C_IN);
+
+ /* We only test PTR. */
+ TEST_COMPARE (qtype, T_PTR);
+
+ unsigned int count;
+ char *tail = NULL;
+
+ if (strstr (qname, "in-addr.arpa") != NULL
+ && sscanf (qname, "%u.%ms", &count, &tail) == 2)
+ TEST_COMPARE_STRING (tail, "0.168.192.in-addr.arpa");
+ else if (sscanf (qname, "%x.%ms", &count, &tail) == 2)
+ {
+ TEST_COMPARE_STRING (tail, "\
+0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa");
+ }
+ else
+ FAIL_EXIT1 ("invalid QNAME: %s\n", qname);
+ free (tail);
+
+ /* We have a bounded number of possible tests. */
+ TEST_VERIFY (count >= 0);
+ TEST_VERIFY (count <= 15);
+
+ struct resolv_response_flags flags = {};
+ resolv_response_init (b, flags);
+ resolv_response_add_question (b, qname, qclass, qtype);
+ resolv_response_section (b, ns_s_an);
+
+ /* Actual answer record, but the wrong name (skipped). */
+ resolv_response_open_record (b, "1.0.0.10.in-addr.arpa", qclass, qtype, 60);
+
+ /* Record the answer. */
+ resolv_response_add_name (b, "test.ptr.example.net");
+ resolv_response_close_record (b);
+
+ /* Add a second section to test section boundary crossing. */
+ resolv_response_section (b, test_items[count].ns_section);
+ /* Semantically incorrect, but hide a T_PTR entry. */
+ resolv_response_open_record (b, qname, qclass, qtype, 60);
+ resolv_response_add_name (b, "wrong.ptr.example.net");
+ resolv_response_close_record (b);
+}
+
+
+/* Perform one check using a reverse lookup. */
+static void
+check_reverse (int af, int count)
+{
+ TEST_VERIFY (af == AF_INET || af == AF_INET6);
+ TEST_VERIFY (count < array_length (test_items));
+
+ char addr[sizeof (struct in6_addr)] = { 0 };
+ socklen_t addrlen;
+ if (af == AF_INET)
+ {
+ addr[0] = (char) 192;
+ addr[1] = (char) 168;
+ addr[2] = (char) 0;
+ addr[3] = (char) count;
+ addrlen = 4;
+ }
+ else
+ {
+ addr[0] = 0x20;
+ addr[1] = 0x01;
+ addr[2] = 0x0d;
+ addr[3] = 0xb8;
+ addr[4] = addr[5] = addr[6] = addr[7] = 0x0;
+ addr[8] = addr[9] = addr[10] = addr[11] = 0x0;
+ addr[12] = 0x0;
+ addr[13] = 0x0;
+ addr[14] = 0x0;
+ addr[15] = count;
+ addrlen = 16;
+ }
+
+ h_errno = 0;
+ struct hostent *answer = gethostbyaddr (addr, addrlen, af);
+ TEST_VERIFY (answer == NULL);
+ TEST_VERIFY (h_errno == NO_RECOVERY);
+ if (answer != NULL)
+ printf ("error: unexpected success: %s\n",
+ support_format_hostent (answer));
+}
+
+static int
+do_test (void)
+{
+ struct resolv_test *obj = resolv_test_start
+ ((struct resolv_redirect_config)
+ {
+ .response_callback = response
+ });
+
+ for (int i = 0; test_items[i].test != NULL; i++)
+ {
+ check_reverse (AF_INET, i);
+ check_reverse (AF_INET6, i);
+ }
+
+ resolv_test_end (obj);
+
+ return 0;
+}
+
+#include <support/test-driver.c>

View File

@ -0,0 +1,314 @@
commit 9344c796f7a4ac8f2c59de63f3e1e936b51e817d
Author: Carlos O'Donell <carlos@redhat.com>
Date: Fri Mar 20 17:14:33 2026 -0400
resolv: Check hostname for validity (CVE-2026-4438)
The processed hostname in getanswer_ptr should be correctly checked to
avoid invalid characters from being allowed, including shell
metacharacters. It is a security issue to fail to check the returned
hostname for validity.
A regression test is added for invalid metacharacters and other cases
of invalid or valid characters.
No regressions on x86_64-linux-gnu.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit e10977481f4db4b2a3ce34fa4c3a1e26651ae312)
diff --git a/resolv/Makefile b/resolv/Makefile
index 8dba948b632d3abc..87a5c1ccc6dabc8a 100644
--- a/resolv/Makefile
+++ b/resolv/Makefile
@@ -107,6 +107,7 @@ tests += \
tst-resolv-dns-section \
tst-resolv-edns \
tst-resolv-invalid-cname \
+ tst-resolv-invalid-ptr \
tst-resolv-network \
tst-resolv-noaaaa \
tst-resolv-noaaaa-vc \
@@ -305,6 +306,8 @@ $(objpfx)tst-resolv-res_init-thread: $(objpfx)libresolv.so \
$(shared-thread-library)
$(objpfx)tst-resolv-invalid-cname: $(objpfx)libresolv.so \
$(shared-thread-library)
+$(objpfx)tst-resolv-invalid-ptr: $(objpfx)libresolv.so \
+ $(shared-thread-library)
$(objpfx)tst-resolv-noaaaa: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-noaaaa-vc: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-nondecimal: $(objpfx)libresolv.so $(shared-thread-library)
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index 74a7c08d0f055d6e..b8f5d61b2ae20a4e 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -866,7 +866,7 @@ getanswer_ptr (unsigned char *packet, size_t packetlen,
char hname[MAXHOSTNAMELEN + 1];
if (__ns_name_unpack (c.begin, c.end, rr.rdata,
name_buffer, sizeof (name_buffer)) < 0
- || !__res_binary_hnok (expected_name)
+ || !__res_binary_hnok (name_buffer)
|| __ns_name_ntop (name_buffer, hname, sizeof (hname)) < 0)
{
*h_errnop = NO_RECOVERY;
diff --git a/resolv/tst-resolv-invalid-ptr.c b/resolv/tst-resolv-invalid-ptr.c
new file mode 100644
index 0000000000000000..0c802ab96780efb0
--- /dev/null
+++ b/resolv/tst-resolv-invalid-ptr.c
@@ -0,0 +1,255 @@
+/* Test handling of invalid T_PTR results (bug 34015).
+ Copyright (C) 2022-2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <array_length.h>
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/format_nss.h>
+#include <support/resolv_test.h>
+#include <support/support.h>
+
+/* Name of test, the answer, the expected error return, and if we
+ expect the call to fail. */
+struct item {
+ const char *test;
+ const char *answer;
+ int expected;
+ bool fail;
+};
+
+static const struct item test_items[] =
+ {
+ /* Test for invalid characters. */
+ { "Invalid use of \"|\"",
+ "test.|.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \"&\"",
+ "test.&.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \";\"",
+ "test.;.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \"<\"",
+ "test.<.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \">\"",
+ "test.>.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \"(\"",
+ "test.(.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \")\"",
+ "test.).ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \"$\"",
+ "test.$.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \"`\"",
+ "test.`.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \"\\\"",
+ "test.\\.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \"\'\"",
+ "test.'.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \"\"\"",
+ "test.\".ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \" \"",
+ "test. .ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \"\\t\"",
+ "test.\t.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \"\\n\"",
+ "test.\n.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \"\\r\"",
+ "test.\r.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \"*\"",
+ "test.*.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \"?\"",
+ "test.?.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \"[\"",
+ "test.[.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \"]\"",
+ "test.].ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \",\"",
+ "test.,.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \"~\"",
+ "test.~.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \":\"",
+ "test.:.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \"!\"",
+ "test.!.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \"@\"",
+ "test.@.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \"#\"",
+ "test.#.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \"%\"",
+ "test.%%.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of \"^\"",
+ "test.^.ptr.example", NO_RECOVERY, true },
+
+ /* Test for invalid UTF-8 characters (2-byte, 4-byte, 6-byte). */
+ { "Invalid use of UTF-8 (2-byte, U+00C0-U+00C2)",
+ "ÁÂÃ.test.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of UTF-8 (4-byte, U+0750-U+0752)",
+ "ݐݑݒ.test.ptr.example", NO_RECOVERY, true },
+ { "Invalid use of UTF-8 (6-byte, U+0904-U+0906)",
+ "ऄअआ.test.ptr.example", NO_RECOVERY, true },
+
+ /* Test for "-" which may be valid depending on position. */
+ { "Invalid leading \"-\"",
+ "-test.ptr.example", NO_RECOVERY, true },
+ { "Valid trailing \"-\"",
+ "test-.ptr.example", 0, false },
+ { "Valid mid-label use of \"-\"",
+ "te-st.ptr.example", 0, false },
+
+ /* Test for "_" which is always valid in any position. */
+ { "Valid leading use of \"_\"",
+ "_test.ptr.example", 0, false },
+ { "Valid mid-label use of \"_\"",
+ "te_st.ptr.example", 0, false },
+ { "Valid trailing use of \"_\"",
+ "test_.ptr.example", 0, false },
+
+ /* Sanity test the broader set [A-Za-z0-9_-] of valid characters. */
+ { "Valid \"[A-Z]\"",
+ "test.ABCDEFGHIJKLMNOPQRSTUVWXYZ.ptr.example", 0, false },
+ { "Valid \"[a-z]\"",
+ "test.abcdefghijklmnopqrstuvwxyz.ptr.example", 0, false },
+ { "Valid \"[0-9]\"",
+ "test.0123456789.ptr.example", 0, false },
+ { "Valid mixed use of \"[A-Za-z0-9_-]\"",
+ "test.012abcABZ_-.ptr.example", 0, false },
+ };
+
+static void
+response (const struct resolv_response_context *ctx,
+ struct resolv_response_builder *b,
+ const char *qname, uint16_t qclass, uint16_t qtype)
+{
+ TEST_COMPARE (qclass, C_IN);
+
+ /* We only test PTR. */
+ TEST_COMPARE (qtype, T_PTR);
+
+ unsigned int count, count1;
+ char *tail = NULL;
+
+ /* The test implementation can handle up to 255 tests. */
+ if (strstr (qname, "in-addr.arpa") != NULL
+ && sscanf (qname, "%u.%ms", &count, &tail) == 2)
+ TEST_COMPARE_STRING (tail, "0.168.192.in-addr.arpa");
+ else if (sscanf (qname, "%x.%x.%ms", &count, &count1, &tail) == 3)
+ {
+ TEST_COMPARE_STRING (tail, "\
+0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa");
+ count |= count1 << 4;
+ }
+ else
+ FAIL_EXIT1 ("invalid QNAME: %s\n", qname);
+ free (tail);
+
+ /* Cross check. Count has a fixed bound (soft limit). */
+ TEST_VERIFY (count >= 0 && count <= 255);
+
+ /* We have a fixed number of tests (hard limit). */
+ TEST_VERIFY_EXIT (count < array_length (test_items));
+
+ struct resolv_response_flags flags = {};
+ resolv_response_init (b, flags);
+ resolv_response_add_question (b, qname, qclass, qtype);
+ resolv_response_section (b, ns_s_an);
+
+ /* Actual answer record. */
+ resolv_response_open_record (b, qname, qclass, qtype, 60);
+
+ /* Record the answer. */
+ resolv_response_add_name (b, test_items[count].answer);
+ resolv_response_close_record (b);
+}
+
+/* Perform one check using a reverse lookup. */
+static void
+check_reverse (int af, int count)
+{
+ TEST_VERIFY (af == AF_INET || af == AF_INET6);
+ TEST_VERIFY_EXIT (count < array_length (test_items));
+
+ /* Generate an address to query for each test. */
+ char addr[sizeof (struct in6_addr)] = { 0 };
+ socklen_t addrlen;
+ if (af == AF_INET)
+ {
+ addr[0] = (char) 192;
+ addr[1] = (char) 168;
+ addr[2] = (char) 0;
+ addr[3] = (char) count;
+ addrlen = 4;
+ }
+ else
+ {
+ addr[0] = 0x20;
+ addr[1] = 0x01;
+ addr[2] = 0x0d;
+ addr[3] = 0xb8;
+ addr[4] = addr[5] = addr[6] = addr[7] = 0x0;
+ addr[8] = addr[9] = addr[10] = addr[11] = 0x0;
+ addr[12] = 0x0;
+ addr[13] = 0x0;
+ addr[14] = 0x0;
+ addr[15] = (char) count;
+ addrlen = 16;
+ }
+
+ h_errno = 0;
+ struct hostent *answer = gethostbyaddr (addr, addrlen, af);
+
+ /* Verify h_errno is as expected. */
+ TEST_COMPARE (h_errno, test_items[count].expected);
+ if (h_errno != test_items[count].expected)
+ /* And print more information if it's not. */
+ printf ("INFO: %s\n", test_items[count].test);
+
+ if (test_items[count].fail)
+ {
+ /* We expected a failure so verify answer is NULL. */
+ TEST_VERIFY (answer == NULL);
+ /* If it's not NULL we should print out what we received. */
+ if (answer != NULL)
+ printf ("error: unexpected success: %s\n",
+ support_format_hostent (answer));
+ }
+ else
+ /* We don't expect a failure so answer must be valid. */
+ TEST_COMPARE_STRING (answer->h_name, test_items[count].answer);
+}
+
+static int
+do_test (void)
+{
+ struct resolv_test *obj = resolv_test_start
+ ((struct resolv_redirect_config)
+ {
+ .response_callback = response
+ });
+
+ for (int i = 0; i < array_length (test_items); i++)
+ {
+ check_reverse (AF_INET, i);
+ check_reverse (AF_INET6, i);
+ }
+ resolv_test_end (obj);
+
+ return 0;
+}
+
+#include <support/test-driver.c>

View File

@ -0,0 +1,127 @@
commit 0dc95ae10929aba1cc660e97cfc94903c2568efa
Author: Xi Ruoyao <xry111@xry111.site>
Date: Tue Feb 3 16:20:12 2026 +0800
elf: parse /proc/self/maps as the last resort to find the gap for tst-link-map-contiguous-ldso
The initialization process of libc.so calls mmap() several times and the
kernel may lay the maps into the gap. If all pages in the gap are
occupied, the test would not be able to find the gap with mmap() and the
test would fail.
The failure reproduces most frequently on LoongArch because with the
commonly used page size (16 KiB) the gap only contains 4 pages and the
probability they are all occupied is not near to zero.
With the changes in the patch, a test run may output:
info: ld.so link map is not contiguous
info: object "/dev/zero" found at 0x7ffff1fe0000 - 0x7ffff1fe4000
info: anonymous mapping found at 0x7ffff1fe4000 - 0x7ffff1fec000
Also take the chance to fix a mistake in the "object found at" message
which has puzzled me during the initial debug session.
Signed-off-by: Xi Ruoyao <xry111@xry111.site>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit aed8390a6a22e5751fc12704c0c5f2a8271fc286)
diff --git a/elf/tst-link-map-contiguous-ldso.c b/elf/tst-link-map-contiguous-ldso.c
index 04de808bb234fe38..f0e26682f2858414 100644
--- a/elf/tst-link-map-contiguous-ldso.c
+++ b/elf/tst-link-map-contiguous-ldso.c
@@ -18,15 +18,73 @@
#include <dlfcn.h>
#include <gnu/lib-names.h>
+#include <inttypes.h>
#include <link.h>
#include <stdbool.h>
#include <stdio.h>
#include <support/check.h>
+#include <support/support.h>
#include <support/xdlfcn.h>
#include <support/xunistd.h>
+#include <support/xstdio.h>
#include <sys/mman.h>
#include <unistd.h>
+/* Slow path in case we cannot find a gap with mmap (when the runtime has
+ mapped all the pages in the gap for some reason). */
+static bool
+find_gap_with_proc_self_map (const struct link_map *l)
+{
+ int pagesize = getpagesize ();
+
+ support_need_proc ("Reads /proc/self/maps to find gap in ld.so mapping");
+
+ /* Parse /proc/self/maps and find all the mappings in the ld.so range
+ but not from ld.so. */
+ FILE *f = xfopen ("/proc/self/maps", "r");
+ char *line = NULL, *path_ldso = NULL;
+ size_t len;
+ bool found = false;
+ while (xgetline (&line, &len, f))
+ {
+ uintptr_t from, to;
+ char *path = NULL;
+ int r = sscanf (line, "%" SCNxPTR "-%" SCNxPTR "%*s%*s%*s%*s%ms",
+ &from, &to, &path);
+
+ TEST_VERIFY (r == 2 || r == 3);
+ TEST_COMPARE (from % pagesize, 0);
+ TEST_COMPARE (to % pagesize, 0);
+
+ if (path_ldso == NULL && l->l_map_start == from)
+ {
+ TEST_COMPARE (r, 3);
+ path_ldso = path;
+ continue;
+ }
+
+ if (from > l->l_map_start && to < l->l_map_end
+ && (r == 2 || (path_ldso != NULL && strcmp (path, path_ldso))))
+ {
+ if (r == 2)
+ printf ("info: anonymous mapping found at 0x%" PRIxPTR " - 0x%"
+ PRIxPTR "\n", from, to);
+ else
+ printf ("info: object \"%s\" found at 0x%" PRIxPTR " - 0x%"
+ PRIxPTR "\n", path, from, to);
+
+ found = true;
+ }
+
+ free (path);
+ }
+
+ free (path_ldso);
+ free (line);
+ xfclose (f);
+ return found;
+}
+
static int
do_test (void)
{
@@ -64,16 +122,18 @@ do_test (void)
if ((void *) dlfo.dlfo_link_map != (void *) l)
{
printf ("info: object \"%s\" found at %p\n",
- dlfo.dlfo_link_map->l_name, ptr);
+ dlfo.dlfo_link_map->l_name, expected);
gap_found = true;
}
}
else
TEST_COMPARE (dlfo_ret, -1);
+
xmunmap (ptr, 1);
addr += pagesize;
}
- if (!gap_found)
+
+ if (!gap_found && !find_gap_with_proc_self_map (l))
FAIL ("no ld.so gap found");
}
else

View File

@ -2357,7 +2357,7 @@ update_gconv_modules_cache ()
%endif
%changelog
* Thu Apr 02 2026 Eduard Abdullin <eabdullin@almalinux.org> - 2.39-119.alma.1
* Fri Apr 03 2026 Eduard Abdullin <eabdullin@almalinux.org> - 2.39-120.alma.1
- Overwrite target for x86_64_v2
- Update patch-git.lua to handle AlmaLinux branches correctly