Overwrite target for x86_64_v2
Update patch-git.lua to handle AlmaLinux branches correctly
This commit is contained in:
commit
9e9c50d8ae
287
glibc-upstream-2.39-289.patch
Normal file
287
glibc-upstream-2.39-289.patch
Normal 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>
|
||||
36
glibc-upstream-2.39-290.patch
Normal file
36
glibc-upstream-2.39-290.patch
Normal 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) };
|
||||
25
glibc-upstream-2.39-291.patch
Normal file
25
glibc-upstream-2.39-291.patch
Normal 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; \
|
||||
27
glibc-upstream-2.39-292.patch
Normal file
27
glibc-upstream-2.39-292.patch
Normal 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
|
||||
234
glibc-upstream-2.39-293.patch
Normal file
234
glibc-upstream-2.39-293.patch
Normal 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>
|
||||
314
glibc-upstream-2.39-294.patch
Normal file
314
glibc-upstream-2.39-294.patch
Normal 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>
|
||||
127
glibc-upstream-2.39-295.patch
Normal file
127
glibc-upstream-2.39-295.patch
Normal 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
|
||||
@ -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
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user