diff --git a/SOURCES/RHEL-18039-1.patch b/SOURCES/RHEL-18039-1.patch
new file mode 100644
index 0000000000000000000000000000000000000000..549b26f982c3ea1c2a8914b4b718f3f1a6a6d952
--- /dev/null
+++ b/SOURCES/RHEL-18039-1.patch
@@ -0,0 +1,79 @@
+commit 95f61610f3e481d191b6184432342236fd59186d
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Wed Jul 24 12:06:47 2024 +0200
+
+    resolv: Support clearing option flags with a “-” prefix (bug 14799)
+    
+    I think using a “-” prefix is less confusing than introducing
+    double-negation construct (“no-no-tld-query”).
+    
+    Reviewed-by: DJ Delorie <dj@redhat.com>
+
+diff --git a/resolv/res_init.c b/resolv/res_init.c
+index 263263d474721545..243532b3ade338d8 100644
+--- a/resolv/res_init.c
++++ b/resolv/res_init.c
+@@ -682,27 +682,29 @@ res_setoptions (struct resolv_conf_parser *parser, const char *options)
+           {
+             char str[22];
+             uint8_t len;
+-            uint8_t clear;
+             unsigned long int flag;
+           } options[] = {
+ #define STRnLEN(str) str, sizeof (str) - 1
+-            { STRnLEN ("rotate"), 0, RES_ROTATE },
+-            { STRnLEN ("edns0"), 0, RES_USE_EDNS0 },
+-            { STRnLEN ("single-request-reopen"), 0, RES_SNGLKUPREOP },
+-            { STRnLEN ("single-request"), 0, RES_SNGLKUP },
+-            { STRnLEN ("no_tld_query"), 0, RES_NOTLDQUERY },
+-            { STRnLEN ("no-tld-query"), 0, RES_NOTLDQUERY },
+-            { STRnLEN ("no-reload"), 0, RES_NORELOAD },
+-            { STRnLEN ("use-vc"), 0, RES_USEVC },
+-            { STRnLEN ("trust-ad"), 0, RES_TRUSTAD },
+-            { STRnLEN ("no-aaaa"), 0, RES_NOAAAA },
++            { STRnLEN ("rotate"), RES_ROTATE },
++            { STRnLEN ("edns0"),  RES_USE_EDNS0 },
++            { STRnLEN ("single-request-reopen"), RES_SNGLKUPREOP },
++            { STRnLEN ("single-request"), RES_SNGLKUP },
++            { STRnLEN ("no_tld_query"), RES_NOTLDQUERY },
++            { STRnLEN ("no-tld-query"), RES_NOTLDQUERY },
++            { STRnLEN ("no-reload"), RES_NORELOAD },
++            { STRnLEN ("use-vc"),  RES_USEVC },
++            { STRnLEN ("trust-ad"), RES_TRUSTAD },
++            { STRnLEN ("no-aaaa"), RES_NOAAAA },
+           };
+ #define noptions (sizeof (options) / sizeof (options[0]))
++          bool negate_option = *cp == '-';
++          if (negate_option)
++            ++cp;
+           for (int i = 0; i < noptions; ++i)
+             if (strncmp (cp, options[i].str, options[i].len) == 0)
+               {
+-                if (options[i].clear)
+-                  parser->template.options &= options[i].flag;
++                if (negate_option)
++                  parser->template.options &= ~options[i].flag;
+                 else
+                   parser->template.options |= options[i].flag;
+                 break;
+diff --git a/resolv/tst-resolv-res_init-skeleton.c b/resolv/tst-resolv-res_init-skeleton.c
+index 6bef62cde2cbf8cd..d3a19eb305d41467 100644
+--- a/resolv/tst-resolv-res_init-skeleton.c
++++ b/resolv/tst-resolv-res_init-skeleton.c
+@@ -679,6 +679,16 @@ struct test_case test_cases[] =
+      "; nameserver[0]: [192.0.2.1]:53\n",
+      .res_options = "attempts:5 ndots:3 edns0 ",
+     },
++    {.name = "RES_OPTIONS can clear flags",
++     .conf = "options ndots:2 use-vc no-aaaa edns0\n"
++     "nameserver 192.0.2.1\n",
++     .expected = "options ndots:3 use-vc\n"
++     "search example.com\n"
++     "; search[0]: example.com\n"
++     "nameserver 192.0.2.1\n"
++     "; nameserver[0]: [192.0.2.1]:53\n",
++     .res_options = "ndots:3 -edns0 -no-aaaa",
++    },
+     {.name = "many search list entries (bug 19569)",
+      .conf = "nameserver 192.0.2.1\n"
+      "search corp.example.com support.example.com"
diff --git a/SOURCES/RHEL-18039-2.patch b/SOURCES/RHEL-18039-2.patch
new file mode 100644
index 0000000000000000000000000000000000000000..9834166e04ad577bd69e85c14ebe6a53a87268c7
--- /dev/null
+++ b/SOURCES/RHEL-18039-2.patch
@@ -0,0 +1,204 @@
+commit 765325951ac5c7d072278c9424930b29657e9758
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Wed Jul 24 12:06:47 2024 +0200
+
+    resolv: Implement strict-error stub resolver option (bug 27929)
+    
+    For now, do not enable this mode by default due to the potential
+    impact on compatibility with existing deployments.
+    
+    Reviewed-by: DJ Delorie <dj@redhat.com>
+
+diff --git a/resolv/res_init.c b/resolv/res_init.c
+index 243532b3ade338d8..b838dc70642e1935 100644
+--- a/resolv/res_init.c
++++ b/resolv/res_init.c
+@@ -695,6 +695,7 @@ res_setoptions (struct resolv_conf_parser *parser, const char *options)
+             { STRnLEN ("use-vc"),  RES_USEVC },
+             { STRnLEN ("trust-ad"), RES_TRUSTAD },
+             { STRnLEN ("no-aaaa"), RES_NOAAAA },
++            { STRnLEN ("strict-error"), RES_STRICTERR },
+           };
+ #define noptions (sizeof (options) / sizeof (options[0]))
+           bool negate_option = *cp == '-';
+diff --git a/resolv/res_send.c b/resolv/res_send.c
+index 9c77613f374e5469..9a284ed44aa8cc2e 100644
+--- a/resolv/res_send.c
++++ b/resolv/res_send.c
+@@ -1234,21 +1234,38 @@ send_dg(res_state statp,
+ 
+ 		if (thisansp_error) {
+ 		next_ns:
+-			if (recvresp1 || (buf2 != NULL && recvresp2)) {
+-			  *resplen2 = 0;
+-			  return resplen;
+-			}
+-			if (buf2 != NULL && !single_request)
++		        /* Outside of strict-error mode, use the first
++			   response even if the second response is an
++			   error.  This allows parallel resolution to
++			   succeed even if the recursive resolver
++			   always answers with SERVFAIL for AAAA
++			   queries (which still happens in practice
++			   unfortunately).
++
++			   In strict-error mode, always switch to the
++			   next server and try to get a response from
++			   there.  */
++			if ((statp->options & RES_STRICTERR) == 0)
+ 			  {
+-			    /* No data from the first reply.  */
+-			    resplen = 0;
+-			    /* We are waiting for a possible second reply.  */
+-			    if (matching_query == 1)
+-			      recvresp1 = 1;
+-			    else
+-			      recvresp2 = 1;
+-
+-			    goto wait;
++			    if (recvresp1 || (buf2 != NULL && recvresp2))
++			      {
++				*resplen2 = 0;
++				return resplen;
++			      }
++
++			    if (buf2 != NULL && !single_request)
++			      {
++				/* No data from the first reply.  */
++				resplen = 0;
++				/* We are waiting for a possible
++				   second reply.  */
++				if (matching_query == 1)
++				  recvresp1 = 1;
++				else
++				  recvresp2 = 1;
++
++				goto wait;
++			      }
+ 			  }
+ 
+ 			/* don't retry if called from dig */
+diff --git a/resolv/resolv.h b/resolv/resolv.h
+index f40d6c58cee0f585..b8a0f66a5fd50e22 100644
+--- a/resolv/resolv.h
++++ b/resolv/resolv.h
+@@ -133,6 +133,7 @@ struct res_sym {
+ #define RES_NORELOAD    0x02000000 /* No automatic configuration reload.  */
+ #define RES_TRUSTAD     0x04000000 /* Request AD bit, keep it in responses.  */
+ #define RES_NOAAAA      0x08000000 /* Suppress AAAA queries.  */
++#define RES_STRICTERR   0x10000000 /* Report more DNS errors as errors.  */
+ 
+ #define RES_DEFAULT	(RES_RECURSE|RES_DEFNAMES|RES_DNSRCH)
+ 
+diff --git a/resolv/tst-resolv-res_init-skeleton.c b/resolv/tst-resolv-res_init-skeleton.c
+index d3a19eb305d41467..e41bcebd9d9a8024 100644
+--- a/resolv/tst-resolv-res_init-skeleton.c
++++ b/resolv/tst-resolv-res_init-skeleton.c
+@@ -129,6 +129,7 @@ print_resp (FILE *fp, res_state resp)
+         print_option_flag (fp, &options, RES_NORELOAD, "no-reload");
+         print_option_flag (fp, &options, RES_TRUSTAD, "trust-ad");
+         print_option_flag (fp, &options, RES_NOAAAA, "no-aaaa");
++        print_option_flag (fp, &options, RES_STRICTERR, "strict-error");
+         fputc ('\n', fp);
+         if (options != 0)
+           fprintf (fp, "; error: unresolved option bits: 0x%x\n", options);
+@@ -741,6 +742,15 @@ struct test_case test_cases[] =
+      "nameserver 192.0.2.1\n"
+      "; nameserver[0]: [192.0.2.1]:53\n"
+     },
++    {.name = "strict-error flag",
++     .conf = "options strict-error\n"
++     "nameserver 192.0.2.1\n",
++     .expected = "options strict-error\n"
++     "search example.com\n"
++     "; search[0]: example.com\n"
++     "nameserver 192.0.2.1\n"
++     "; nameserver[0]: [192.0.2.1]:53\n"
++    },
+     { NULL }
+   };
+ 
+diff --git a/resolv/tst-resolv-semi-failure.c b/resolv/tst-resolv-semi-failure.c
+index aa9798b5a7dfaa88..b7681210f450bb5a 100644
+--- a/resolv/tst-resolv-semi-failure.c
++++ b/resolv/tst-resolv-semi-failure.c
+@@ -67,6 +67,9 @@ response (const struct resolv_response_context *ctx,
+   resolv_response_close_record (b);
+ }
+ 
++/* Set to 1 if strict error checking is enabled.  */
++static int do_strict_error;
++
+ static void
+ check_one (void)
+ {
+@@ -83,7 +86,10 @@ check_one (void)
+       struct addrinfo *ai;
+       int ret = getaddrinfo ("www.example", "80", &hints, &ai);
+       const char *expected;
+-      if (ret == 0 && ai->ai_next != NULL)
++      /* In strict-error mode, a switch to the second name server
++         happens, and both responses are received, so a single
++         response is a bug.  */
++      if (do_strict_error || (ret == 0 && ai->ai_next != NULL))
+         expected = ("address: STREAM/TCP 192.0.2.17 80\n"
+                     "address: STREAM/TCP 2001:db8::1 80\n");
+       else
+@@ -99,33 +105,36 @@ check_one (void)
+ static int
+ do_test (void)
+ {
+-  for (int do_single_lookup = 0; do_single_lookup < 2; ++do_single_lookup)
+-    {
+-      struct resolv_test *aux = resolv_test_start
+-        ((struct resolv_redirect_config)
+-         {
+-           .response_callback = response,
+-         });
++  for (do_strict_error = 0; do_strict_error < 2; ++do_strict_error)
++    for (int do_single_lookup = 0; do_single_lookup < 2; ++do_single_lookup)
++      {
++        struct resolv_test *aux = resolv_test_start
++          ((struct resolv_redirect_config)
++           {
++             .response_callback = response,
++           });
+ 
+-      if (do_single_lookup)
+-        _res.options |= RES_SNGLKUP;
++        if (do_strict_error)
++          _res.options |= RES_STRICTERR;
++        if (do_single_lookup)
++          _res.options |= RES_SNGLKUP;
+ 
+-      for (int do_fail_aaaa = 0; do_fail_aaaa < 2; ++do_fail_aaaa)
+-        {
+-          fail_aaaa = do_fail_aaaa;
++        for (int do_fail_aaaa = 0; do_fail_aaaa < 2; ++do_fail_aaaa)
++          {
++            fail_aaaa = do_fail_aaaa;
+ 
+-          rcode = 2; /* SERVFAIL.  */
+-          check_one ();
++            rcode = 2; /* SERVFAIL.  */
++            check_one ();
+ 
+-          rcode = 4; /* NOTIMP.  */
+-          check_one ();
++            rcode = 4; /* NOTIMP.  */
++            check_one ();
+ 
+-          rcode = 5; /* REFUSED.  */
+-          check_one ();
+-        }
++            rcode = 5; /* REFUSED.  */
++            check_one ();
++          }
+ 
+-      resolv_test_end (aux);
+-    }
++        resolv_test_end (aux);
++      }
+ 
+   return 0;
+ }
diff --git a/SOURCES/glibc-rh2292195-1.patch b/SOURCES/glibc-rh2292195-1.patch
new file mode 100644
index 0000000000000000000000000000000000000000..fc5bbfd11c6a0ba2afd83c73f5f7a1c8d60accbc
--- /dev/null
+++ b/SOURCES/glibc-rh2292195-1.patch
@@ -0,0 +1,72 @@
+commit 086910fc41655152812b515dc324d2ac0dc36e67
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Thu Jun 20 10:32:16 2024 +0200
+
+    malloc: Always install mtrace (bug 31892)
+    
+    Generation of the Perl script does not depend on Perl, so we can
+    always install it even if $(PERL) is not set during the build.
+    
+    Change the malloc/mtrace.pl text substition not to rely on $(PERL).
+    Instead use PATH at run time to find the Perl interpreter. The Perl
+    interpreter cannot execute directly a script that starts with
+    “#! /bin/sh”: it always executes it with /bin/sh.  There is no
+    perl command line switch to disable this behavior.  Instead, use
+    the Perl require function to execute the script.  The additional
+    shift calls remove the “.” shell arguments.  Perl interprets the
+    “.” as a string concatenation operator, making the expression
+    syntactically valid.
+    
+    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+
+diff --git a/malloc/Makefile b/malloc/Makefile
+index cc14cf66c9661f99..02aff1bd1dc664c3 100644
+--- a/malloc/Makefile
++++ b/malloc/Makefile
+@@ -250,7 +250,6 @@ others-extras = mcheck-init.o
+ aux := set-freeres thread-freeres
+ 
+ # The Perl script to analyze the output of the mtrace functions.
+-ifneq ($(PERL),no)
+ install-bin-script = mtrace
+ generated += mtrace
+ 
+@@ -261,7 +260,6 @@ address-width=10
+ else
+ address-width=18
+ endif
+-endif
+ 
+ # Unless we get a test for the availability of libgd which also works
+ # for cross-compiling we disable the memusagestat generation in this
+@@ -349,7 +347,7 @@ sLIBdir := $(shell echo $(slibdir) | sed 's,lib\(\|64\)$$,\\\\$$LIB,')
+ 
+ $(objpfx)mtrace: mtrace.pl
+ 	rm -f $@.new
+-	sed -e 's|@PERL@|$(PERL)|' -e 's|@XXX@|$(address-width)|' \
++	sed -e 's|@XXX@|$(address-width)|' \
+ 	    -e 's|@VERSION@|$(version)|' \
+ 	    -e 's|@PKGVERSION@|$(PKGVERSION)|' \
+ 	    -e 's|@REPORT_BUGS_TO@|$(REPORT_BUGS_TO)|' $^ > $@.new \
+diff --git a/malloc/mtrace.pl b/malloc/mtrace.pl
+index 075da0d9f11da15c..dc6085820e62092c 100644
+--- a/malloc/mtrace.pl
++++ b/malloc/mtrace.pl
+@@ -1,6 +1,6 @@
+-#! @PERL@
+-eval "exec @PERL@ -S $0 $@"
+-    if 0;
++#! /bin/sh
++eval exec "perl -e 'shift; \$progname=shift; shift; require \$progname'" . "$0" . "$@"
++   if 0;
+ # Copyright (C) 1997-2024 Free Software Foundation, Inc.
+ # This file is part of the GNU C Library.
+ # Based on the mtrace.awk script.
+@@ -22,7 +22,6 @@ eval "exec @PERL@ -S $0 $@"
+ $VERSION = "@VERSION@";
+ $PKGVERSION = "@PKGVERSION@";
+ $REPORT_BUGS_TO = '@REPORT_BUGS_TO@';
+-$progname = $0;
+ 
+ sub usage {
+     print "Usage: mtrace [OPTION]... [Binary] MtraceData\n";
diff --git a/SOURCES/glibc-rh2292195-2.patch b/SOURCES/glibc-rh2292195-2.patch
new file mode 100644
index 0000000000000000000000000000000000000000..61436e85379054af25f8d3b0a41ee67245516497
--- /dev/null
+++ b/SOURCES/glibc-rh2292195-2.patch
@@ -0,0 +1,84 @@
+commit dd144dce21c864781fade4561581d50fb4549956
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Thu Jun 20 20:55:10 2024 +0200
+
+    malloc: Replace shell/Perl gate in mtrace
+    
+    The previous version expanded $0 and $@ twice.
+    
+    The new version defines a q no-op shell command.  The Perl syntax
+    error is masked by the eval Perl function.  The q { … } construct
+    is executed by the shell without errors because the q shell function
+    was defined, but treated as a non-expanding quoted string by Perl,
+    effectively hiding its context from the Perl interpreter.  As before
+    the script is read by require instead of executed directly, to avoid
+    infinite recursion because the #! line contains /bin/sh.
+    
+    Introduce the “fatal” function to produce diagnostics that are not
+    suppressed by “do”.  Use “do” instead of “require” because it has
+    fewer requirements on the executed script than “require”.
+    
+    Prefix relative paths with './' because “do” (and “require“ before)
+    searches for the script in @INC if the path is relative and does not
+    start with './'.  Use $_ to make the trampoline shorter.
+    
+    Add an Emacs mode marker to indentify the script as a Perl script.
+
+diff --git a/malloc/mtrace.pl b/malloc/mtrace.pl
+index dc6085820e62092c..0a631a07bc4cfbb6 100644
+--- a/malloc/mtrace.pl
++++ b/malloc/mtrace.pl
+@@ -1,6 +1,12 @@
+ #! /bin/sh
+-eval exec "perl -e 'shift; \$progname=shift; shift; require \$progname'" . "$0" . "$@"
+-   if 0;
++# -*- perl -*-
++eval "q () {
++  :
++}";
++q {
++    exec perl -e '$_ = shift; $_ = "./$_" unless m,^/,; do $_' "$0" "$@"
++}
++;
+ # Copyright (C) 1997-2024 Free Software Foundation, Inc.
+ # This file is part of the GNU C Library.
+ # Based on the mtrace.awk script.
+@@ -22,6 +28,7 @@ eval exec "perl -e 'shift; \$progname=shift; shift; require \$progname'" . "$0"
+ $VERSION = "@VERSION@";
+ $PKGVERSION = "@PKGVERSION@";
+ $REPORT_BUGS_TO = '@REPORT_BUGS_TO@';
++$progname = $_;
+ 
+ sub usage {
+     print "Usage: mtrace [OPTION]... [Binary] MtraceData\n";
+@@ -33,6 +40,11 @@ sub usage {
+     exit 0;
+ }
+ 
++sub fatal {
++    print STDERR "$_[0]\n";
++    exit 1;
++}
++
+ # We expect two arguments:
+ #   #1: the complete path to the binary
+ #   #2: the mtrace data filename
+@@ -86,7 +98,7 @@ if ($#ARGV == 0) {
+ 	close (LOCS);
+     }
+ } else {
+-    die "Wrong number of arguments, run $progname --help for help.";
++    fatal "Wrong number of arguments, run $progname --help for help.";
+ }
+ 
+ sub addr2line {
+@@ -148,7 +160,8 @@ sub location {
+ }
+ 
+ $nr=0;
+-open(DATA, "<$data") || die "Cannot open mtrace data file";
++open(DATA, "<$data")
++  or fatal "$progname: Cannot open mtrace data file $data: $!";
+ while (<DATA>) {
+     my @cols = split (' ');
+     my $n, $where;
diff --git a/SOURCES/glibc-rh2292195-3.patch b/SOURCES/glibc-rh2292195-3.patch
new file mode 100644
index 0000000000000000000000000000000000000000..ef2d7f1018c89240e955aea277ef120f0dc128d6
--- /dev/null
+++ b/SOURCES/glibc-rh2292195-3.patch
@@ -0,0 +1,31 @@
+commit 2a6c922f09e7a1c206e0cbdb4424f1cf101a5bda
+Author: Andreas Schwab <schwab@suse.de>
+Date:   Thu Jun 20 14:13:01 2024 +0200
+
+    mtrace: make shell commands robust against meta characters
+    
+    Use the list form of the open function to avoid interpreting meta
+    characters in the arguments.
+
+diff --git a/malloc/mtrace.pl b/malloc/mtrace.pl
+index 0a631a07bc4cfbb6..32b4da935f7c7c4a 100644
+--- a/malloc/mtrace.pl
++++ b/malloc/mtrace.pl
+@@ -87,7 +87,7 @@ if ($#ARGV == 0) {
+     }
+     # Set the environment variable LD_TRACE_LOADED_OBJECTS to 2 so the
+     # executable is also printed.
+-    if (open (locs, "env LD_TRACE_LOADED_OBJECTS=2 $prog |")) {
++    if (open (locs, "-|", "env", "LD_TRACE_LOADED_OBJECTS=2", $prog)) {
+ 	while (<locs>) {
+ 	    chop;
+ 	    if (/^.*=> (.*) .(0x[0123456789abcdef]*).$/) {
+@@ -104,7 +104,7 @@ if ($#ARGV == 0) {
+ sub addr2line {
+     my $addr = pop(@_);
+     my $prog = pop(@_);
+-    if (open (ADDR, "addr2line -e $prog $addr|")) {
++    if (open (ADDR, "-|", "addr2line", "-e", $prog, $addr)) {
+ 	my $line = <ADDR>;
+ 	chomp $line;
+ 	close (ADDR);
diff --git a/SOURCES/glibc-upstream-2.39-76.patch b/SOURCES/glibc-upstream-2.39-76.patch
new file mode 100644
index 0000000000000000000000000000000000000000..6203daa2a208507c39c87df48990ef68407ff1e1
--- /dev/null
+++ b/SOURCES/glibc-upstream-2.39-76.patch
@@ -0,0 +1,155 @@
+commit 74630b1bb717fb98f4692261f2be8d5c84851fa3
+Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date:   Mon May 6 13:20:56 2024 -0300
+
+    posix: Fix pidfd_spawn/pidfd_spawnp leak if execve fails (BZ 31695)
+    
+    If the pidfd_spawn/pidfd_spawnp helper process succeeds, but evecve
+    fails for some reason (either with an invalid/non-existent, memory
+    allocation, etc.) the resulting pidfd is never closed, nor returned
+    to caller (so it can call close).
+    
+    Since the process creation failed, it should be up to posix_spawn to
+    also, close the file descriptor in this case (similar to what it
+    does to reap the process).
+    
+    This patch also changes the waitpid with waitid (P_PIDFD) for pidfd
+    case, to avoid a possible pid re-use.
+    
+    Checked on x86_64-linux-gnu.
+    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+    
+    (cherry picked from commit c90cfce849d010474e8cccf3e5bff49a2c8b141f)
+
+diff --git a/posix/tst-spawn2.c b/posix/tst-spawn2.c
+index bb507204a2b25271..b2bad3f1f7e026fd 100644
+--- a/posix/tst-spawn2.c
++++ b/posix/tst-spawn2.c
+@@ -26,6 +26,7 @@
+ #include <stdio.h>
+ 
+ #include <support/check.h>
++#include <support/descriptors.h>
+ #include <tst-spawn.h>
+ 
+ int
+@@ -38,38 +39,53 @@ do_test (void)
+   char * const args[] = { 0 };
+   PID_T_TYPE pid = -1;
+ 
+-  int ret = POSIX_SPAWN (&pid, program, 0, 0, args, environ);
+-  if (ret != ENOENT)
+-    {
+-      errno = ret;
+-      FAIL_EXIT1 ("posix_spawn: %m");
+-    }
+-
+-  /* POSIX states the value returned on pid variable in case of an error
+-     is not specified.  GLIBC will update the value iff the child
+-     execution is successful.  */
+-  if (pid != -1)
+-    FAIL_EXIT1 ("posix_spawn returned pid != -1 (%i)", (int) pid);
+-
+-  /* Check if no child is actually created.  */
+-  TEST_COMPARE (WAITID (P_ALL, 0, NULL, WEXITED), -1);
+-  TEST_COMPARE (errno, ECHILD);
+-
+-  /* Same as before, but with posix_spawnp.  */
+-  char *args2[] = { (char*) program, 0 };
+-
+-  ret = POSIX_SPAWNP (&pid, args2[0], 0, 0, args2, environ);
+-  if (ret != ENOENT)
+-    {
+-      errno = ret;
+-      FAIL_EXIT1 ("posix_spawnp: %m");
+-    }
+-
+-  if (pid != -1)
+-    FAIL_EXIT1 ("posix_spawnp returned pid != -1 (%i)", (int) pid);
+-
+-  TEST_COMPARE (WAITID (P_ALL, 0, NULL, WEXITED), -1);
+-  TEST_COMPARE (errno, ECHILD);
++  {
++    struct support_descriptors *descrs = support_descriptors_list ();
++
++    int ret = POSIX_SPAWN (&pid, program, 0, 0, args, environ);
++    if (ret != ENOENT)
++      {
++	errno = ret;
++	FAIL_EXIT1 ("posix_spawn: %m");
++      }
++
++    /* POSIX states the value returned on pid variable in case of an error
++       is not specified.  GLIBC will update the value iff the child
++       execution is successful.  */
++    if (pid != -1)
++      FAIL_EXIT1 ("posix_spawn returned pid != -1 (%i)", (int) pid);
++
++    /* Check if no child is actually created.  */
++    TEST_COMPARE (WAITID (P_ALL, 0, NULL, WEXITED), -1);
++    TEST_COMPARE (errno, ECHILD);
++
++    /* Also check if there is no leak descriptors.  */
++    support_descriptors_check (descrs);
++    support_descriptors_free (descrs);
++  }
++
++  {
++    /* Same as before, but with posix_spawnp.  */
++    char *args2[] = { (char*) program, 0 };
++
++    struct support_descriptors *descrs = support_descriptors_list ();
++
++    int ret = POSIX_SPAWNP (&pid, args2[0], 0, 0, args2, environ);
++    if (ret != ENOENT)
++      {
++	errno = ret;
++	FAIL_EXIT1 ("posix_spawnp: %m");
++      }
++
++    if (pid != -1)
++      FAIL_EXIT1 ("posix_spawnp returned pid != -1 (%i)", (int) pid);
++
++    TEST_COMPARE (WAITID (P_ALL, 0, NULL, WEXITED), -1);
++    TEST_COMPARE (errno, ECHILD);
++
++    support_descriptors_check (descrs);
++    support_descriptors_free (descrs);
++  }
+ 
+   return 0;
+ }
+diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c
+index e8ed2babb9b13969..f57e92815eaf3c7b 100644
+--- a/sysdeps/unix/sysv/linux/spawni.c
++++ b/sysdeps/unix/sysv/linux/spawni.c
+@@ -449,13 +449,22 @@ __spawnix (int *pid, const char *file,
+ 	 caller to actually collect it.  */
+       ec = args.err;
+       if (ec > 0)
+-	/* There still an unlikely case where the child is cancelled after
+-	   setting args.err, due to a positive error value.  Also there is
+-	   possible pid reuse race (where the kernel allocated the same pid
+-	   to an unrelated process).  Unfortunately due synchronization
+-	   issues where the kernel might not have the process collected
+-	   the waitpid below can not use WNOHANG.  */
+-	__waitpid (new_pid, NULL, 0);
++	{
++	  /* There still an unlikely case where the child is cancelled after
++	     setting args.err, due to a positive error value.  Also there is
++	     possible pid reuse race (where the kernel allocated the same pid
++	     to an unrelated process).  Unfortunately due synchronization
++	     issues where the kernel might not have the process collected
++	     the waitpid below can not use WNOHANG.  */
++	  __waitid (use_pidfd ? P_PIDFD : P_PID,
++		    use_pidfd ? args.pidfd : new_pid,
++		    NULL,
++		    WEXITED);
++	  /* For pidfd we need to also close the file descriptor for the case
++	     where execve fails.  */
++	  if (use_pidfd)
++	    __close_nocancel_nostatus (args.pidfd);
++	}
+     }
+   else
+     ec = errno;
diff --git a/SOURCES/glibc-upstream-2.39-77.patch b/SOURCES/glibc-upstream-2.39-77.patch
new file mode 100644
index 0000000000000000000000000000000000000000..f4c45e77f032639741f56ac121bc370d7e3ebea0
--- /dev/null
+++ b/SOURCES/glibc-upstream-2.39-77.patch
@@ -0,0 +1,107 @@
+commit 6cb25aff8583421cf7a55ddd40abd7bd49176c60
+Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date:   Thu Mar 14 14:59:35 2024 -0300
+
+    math: Fix i386 and m68k fmod/fmodf on static build (BZ 31488)
+    
+    The commit 16439f419b removed the static fmod/fmodf on i386 and m68k
+    with and empty w_fmod.c (required for the ABIs that uses the newly
+    implementation).  This patch fixes by adding the required symbols on
+    the arch-specific w_fmod{f}_compat.c implementation.
+    
+    To statically build fmod fails on some ABI (alpha, s390, sparc) because
+    it does not export the ldexpf128, this is also fixed by this patch.
+    
+    Checked on i686-linux-gnu and with a build for m68k-linux-gnu.
+    
+    Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
+    Tested-by: Aurelien Jarno <aurelien@aurel32.net>
+    (cherry picked from commit 0b716305dfb48c2d13ed4f7d06c082b90c1d226f)
+
+diff --git a/sysdeps/i386/fpu/w_fmod_compat.c b/sysdeps/i386/fpu/w_fmod_compat.c
+index 5ac9995ffd862a7f..528bfc2a135b5251 100644
+--- a/sysdeps/i386/fpu/w_fmod_compat.c
++++ b/sysdeps/i386/fpu/w_fmod_compat.c
+@@ -7,8 +7,9 @@
+ # define LIBM_SVID_COMPAT 1
+ # undef compat_symbol
+ # define compat_symbol(a, b, c, d)
+-#endif
+-#include <math/w_fmod_compat.c>
+-#ifdef SHARED
++# include <math/w_fmod_compat.c>
+ libm_alias_double (__fmod_compat, fmod)
++#else
++#include <math-type-macros-double.h>
++#include <w_fmod_template.c>
+ #endif
+diff --git a/sysdeps/i386/fpu/w_fmodf_compat.c b/sysdeps/i386/fpu/w_fmodf_compat.c
+index cc417e07d39b271d..5a61693e51f98f8f 100644
+--- a/sysdeps/i386/fpu/w_fmodf_compat.c
++++ b/sysdeps/i386/fpu/w_fmodf_compat.c
+@@ -7,8 +7,9 @@
+ # define LIBM_SVID_COMPAT 1
+ # undef compat_symbol
+ # define compat_symbol(a, b, c, d)
+-#endif
+-#include <math/w_fmodf_compat.c>
+-#ifdef SHARED
++# include <math/w_fmodf_compat.c>
+ libm_alias_float (__fmod_compat, fmod)
++#else
++#include <math-type-macros-float.h>
++#include <w_fmod_template.c>
+ #endif
+diff --git a/sysdeps/ieee754/ldbl-opt/s_ldexpl.c b/sysdeps/ieee754/ldbl-opt/s_ldexpl.c
+index 1afbe7d8adbb00ae..932cc4341c53dec3 100644
+--- a/sysdeps/ieee754/ldbl-opt/s_ldexpl.c
++++ b/sysdeps/ieee754/ldbl-opt/s_ldexpl.c
+@@ -17,13 +17,13 @@
+    License along with the GNU C Library; if not, see
+    <https://www.gnu.org/licenses/>.  */
+ 
+-#if IS_IN (libc)
++#if IS_IN (libc) && defined SHARED
+ # define declare_mgen_alias(f,t)
+ #endif
+ #include <math-type-macros-ldouble.h>
+ #include <s_ldexp_template.c>
+ 
+-#if IS_IN (libc)
++#if IS_IN (libc) && defined SHARED
+ long_double_symbol (libc, __ldexpl, ldexpl);
+ long_double_symbol (libc, __wrap_scalbnl, scalbnl);
+ #endif
+diff --git a/sysdeps/m68k/m680x0/fpu/w_fmod_compat.c b/sysdeps/m68k/m680x0/fpu/w_fmod_compat.c
+index 527d4fbed201d4b4..57f38091e6724848 100644
+--- a/sysdeps/m68k/m680x0/fpu/w_fmod_compat.c
++++ b/sysdeps/m68k/m680x0/fpu/w_fmod_compat.c
+@@ -7,8 +7,9 @@
+ # define LIBM_SVID_COMPAT 1
+ # undef compat_symbol
+ # define compat_symbol(a, b, c, d)
+-#endif
+ #include <math/w_fmod_compat.c>
+-#ifdef SHARED
+ libm_alias_double (__fmod_compat, fmod)
++#else
++#include <math-type-macros-double.h>
++#include <w_fmod_template.c>
+ #endif
+diff --git a/sysdeps/m68k/m680x0/fpu/w_fmodf_compat.c b/sysdeps/m68k/m680x0/fpu/w_fmodf_compat.c
+index 5043586b910e765f..88db07f443b0c339 100644
+--- a/sysdeps/m68k/m680x0/fpu/w_fmodf_compat.c
++++ b/sysdeps/m68k/m680x0/fpu/w_fmodf_compat.c
+@@ -7,8 +7,9 @@
+ # define LIBM_SVID_COMPAT 1
+ # undef compat_symbol
+ # define compat_symbol(a, b, c, d)
+-#endif
+-#include <math/w_fmodf_compat.c>
+-#ifdef SHARED
++# include <math/w_fmodf_compat.c>
+ libm_alias_float (__fmod_compat, fmod)
++#else
++#include <math-type-macros-float.h>
++#include <w_fmod_template.c>
+ #endif
diff --git a/SOURCES/glibc-upstream-2.39-78.patch b/SOURCES/glibc-upstream-2.39-78.patch
new file mode 100644
index 0000000000000000000000000000000000000000..2f3022c02caccfe509e0efddc0641c96cbea4e49
--- /dev/null
+++ b/SOURCES/glibc-upstream-2.39-78.patch
@@ -0,0 +1,46 @@
+commit 3950cbd7a18b48c0f272ca41fa60cc135ff3175a
+Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date:   Wed Mar 20 11:31:54 2024 -0300
+
+    math: Fix i386 and m68k exp10 on static build (BZ 31775)
+    
+    The commit 08ddd26814 removed the static exp10 on i386 and m68k with an
+    empty w_exp10.c (required for the ABIs that uses the newly
+    implementation).  This patch fixes by adding the required symbols on the
+    arch-specific w_exp{f}_compat.c implementation.
+    
+    Checked on i686-linux-gnu and with a build for m68k-linux-gnu.
+    
+    Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
+    (cherry picked from commit 1f09aae36aa185b8b1100dfa6b776442279bf580)
+
+diff --git a/sysdeps/i386/fpu/w_exp10_compat.c b/sysdeps/i386/fpu/w_exp10_compat.c
+index b53455386ed8e189..49a0e03385e4bfe3 100644
+--- a/sysdeps/i386/fpu/w_exp10_compat.c
++++ b/sysdeps/i386/fpu/w_exp10_compat.c
+@@ -1,3 +1,8 @@
+ /* i386 provides an optimized __ieee754_exp10.  */
+-#define NO_COMPAT_NEEDED 1
+-#include <math/w_exp10_compat.c>
++#ifdef SHARED
++# define NO_COMPAT_NEEDED 1
++# include <math/w_exp10_compat.c>
++#else
++# include <math-type-macros-double.h>
++# include <w_exp10_template.c>
++#endif
+diff --git a/sysdeps/m68k/m680x0/fpu/w_exp10_compat.c b/sysdeps/m68k/m680x0/fpu/w_exp10_compat.c
+index 0d3e7186261041e3..350f2e4b4d37e569 100644
+--- a/sysdeps/m68k/m680x0/fpu/w_exp10_compat.c
++++ b/sysdeps/m68k/m680x0/fpu/w_exp10_compat.c
+@@ -1,3 +1,8 @@
+ /* m68k provides an optimized __ieee754_exp10.  */
+-#define NO_COMPAT_NEEDED 1
+-#include <math/w_exp10_compat.c>
++#ifdef SHARED
++# define NO_COMPAT_NEEDED 1
++# include <math/w_exp10_compat.c>
++#else
++# include <math-type-macros-double.h>
++# include <w_exp10_template.c>
++#endif
diff --git a/SOURCES/glibc-upstream-2.39-79.patch b/SOURCES/glibc-upstream-2.39-79.patch
new file mode 100644
index 0000000000000000000000000000000000000000..fe3ef5c5e10dc143a1205a22e941ad8b573f37db
--- /dev/null
+++ b/SOURCES/glibc-upstream-2.39-79.patch
@@ -0,0 +1,30 @@
+commit d473c9bb3b6b0448985cd195c558de2a49fd2dc2
+Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date:   Tue May 21 13:52:54 2024 -0300
+
+    math: Fix isnanf128 static build (BZ 31774)
+    
+    Some static implementation of float128 routines might call __isnanf128,
+    which is not provided by the static object.
+    
+    Checked on x86_64-linux-gnu.
+    Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
+    
+    (cherry picked from commit 5d4999e519ec77e75bef920e2540e8605015680a)
+
+diff --git a/sysdeps/ieee754/float128/s_isnanf128.c b/sysdeps/ieee754/float128/s_isnanf128.c
+index 59f71533cedc752e..b73a4e80d707eeb8 100644
+--- a/sysdeps/ieee754/float128/s_isnanf128.c
++++ b/sysdeps/ieee754/float128/s_isnanf128.c
+@@ -11,7 +11,11 @@
+ #include "../ldbl-128/s_isnanl.c"
+ #if !IS_IN (libm)
+ #include <float128-abi.h>
++#ifdef SHARED
+ hidden_ver (__isnanf128_impl, __isnanf128)
++#else
++strong_alias (__isnanf128_impl, __isnanf128)
++#endif
+ _weak_alias (__isnanf128_impl, isnanl)
+ versioned_symbol (libc, __isnanf128_impl, __isnanf128, GLIBC_2_34);
+ #if (SHLIB_COMPAT (libc, FLOAT128_VERSION_M, GLIBC_2_34))
diff --git a/SOURCES/glibc-upstream-2.39-80.patch b/SOURCES/glibc-upstream-2.39-80.patch
new file mode 100644
index 0000000000000000000000000000000000000000..793f597b6fba65ef538bf3d2f8e905149f4aad09
--- /dev/null
+++ b/SOURCES/glibc-upstream-2.39-80.patch
@@ -0,0 +1,66 @@
+commit d2cbfcf1d9a4b539007fe04d33e0bdb82d02a2f2
+Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date:   Wed May 22 15:07:12 2024 -0300
+
+    math: Provide missing math symbols on libc.a (BZ 31781)
+    
+    The libc.a for alpha, s390, and sparcv9 does not provide
+    copysignf64x, copysignf128, frexpf64x, frexpf128, modff64x, and
+    modff128.
+    
+    Checked with a static build for the affected ABIs.
+    Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
+    
+    (cherry picked from commit eaa8113bf0eb599025e3efdbe1bb214ee8dc645a)
+
+diff --git a/sysdeps/ieee754/ldbl-64-128/s_copysignl.c b/sysdeps/ieee754/ldbl-64-128/s_copysignl.c
+index 11b42d04ba61b446..80137847d32c7c08 100644
+--- a/sysdeps/ieee754/ldbl-64-128/s_copysignl.c
++++ b/sysdeps/ieee754/ldbl-64-128/s_copysignl.c
+@@ -1,10 +1,10 @@
+ #include <math_ldbl_opt.h>
+ #include <libm-alias-ldouble.h>
+-#if IS_IN (libc)
++#if IS_IN (libc) && defined SHARED
+ # undef libm_alias_ldouble
+ # define libm_alias_ldouble(from, to)
+ #endif
+ #include <sysdeps/ieee754/ldbl-128/s_copysignl.c>
+-#if IS_IN (libc)
++#if IS_IN (libc) && defined SHARED
+ long_double_symbol (libc, __copysignl, copysignl);
+ #endif
+diff --git a/sysdeps/ieee754/ldbl-64-128/s_frexpl.c b/sysdeps/ieee754/ldbl-64-128/s_frexpl.c
+index 73ac41e40c214394..f5f7d349f78ab64e 100644
+--- a/sysdeps/ieee754/ldbl-64-128/s_frexpl.c
++++ b/sysdeps/ieee754/ldbl-64-128/s_frexpl.c
+@@ -1,10 +1,10 @@
+ #include <math_ldbl_opt.h>
+ #include <libm-alias-ldouble.h>
+-#if IS_IN (libc)
++#if IS_IN (libc) && defined SHARED
+ # undef libm_alias_ldouble
+ # define libm_alias_ldouble(from, to)
+ #endif
+ #include <sysdeps/ieee754/ldbl-128/s_frexpl.c>
+-#if IS_IN (libc)
++#if IS_IN (libc) && defined SHARED
+ long_double_symbol (libc, __frexpl, frexpl);
+ #endif
+diff --git a/sysdeps/ieee754/ldbl-64-128/s_modfl.c b/sysdeps/ieee754/ldbl-64-128/s_modfl.c
+index 7d7aeae111fc6e7a..ba3d31334a0fefa0 100644
+--- a/sysdeps/ieee754/ldbl-64-128/s_modfl.c
++++ b/sysdeps/ieee754/ldbl-64-128/s_modfl.c
+@@ -1,10 +1,10 @@
+ #include <math_ldbl_opt.h>
+ #include <libm-alias-ldouble.h>
+-#if IS_IN (libc)
++#if IS_IN (libc) && defined SHARED
+ # undef libm_alias_ldouble
+ # define libm_alias_ldouble(from, to)
+ #endif
+ #include <sysdeps/ieee754/ldbl-128/s_modfl.c>
+-#if IS_IN (libc)
++#if IS_IN (libc) && defined SHARED
+ long_double_symbol (libc, __modfl, modfl);
+ #endif
diff --git a/SOURCES/glibc-upstream-2.39-81.patch b/SOURCES/glibc-upstream-2.39-81.patch
new file mode 100644
index 0000000000000000000000000000000000000000..9f070f227fedfe032fed867f1b4e16f039b67e08
--- /dev/null
+++ b/SOURCES/glibc-upstream-2.39-81.patch
@@ -0,0 +1,32 @@
+commit a03631124602f2dcef40d46660b96d2e51c44bfd
+Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date:   Fri Apr 5 10:27:29 2024 -0300
+
+    stdlib: fix arc4random fallback to /dev/urandom (BZ 31612)
+    
+    The __getrandom_nocancel used by __arc4random_buf uses
+    INLINE_SYSCALL_CALL (which returns -1/errno) and the loop checks for
+    the return value instead of errno to fallback to /dev/urandom.
+    
+    The malloc code now uses __getrandom_nocancel_nostatus, which uses
+    INTERNAL_SYSCALL_CALL, so there is no need to use the variant that does
+    not set errno (BZ#29624).
+    
+    Checked on x86_64-linux-gnu.
+    
+    Reviewed-by: Xi Ruoyao <xry111@xry111.site>
+    (cherry picked from commit 184b9e530e6326e668709826903b6d30dc6cac3f)
+
+diff --git a/stdlib/arc4random.c b/stdlib/arc4random.c
+index 3ae8fc130234b04d..7818cb9cf66e0f3b 100644
+--- a/stdlib/arc4random.c
++++ b/stdlib/arc4random.c
+@@ -51,7 +51,7 @@ __arc4random_buf (void *p, size_t n)
+ 	  n -= l;
+ 	  continue; /* Interrupted by a signal; keep going.  */
+ 	}
+-      else if (l == -ENOSYS)
++      else if (l < 0 && errno == ENOSYS)
+ 	break; /* No syscall, so fallback to /dev/urandom.  */
+       arc4random_getrandom_failure ();
+     }
diff --git a/SOURCES/glibc-upstream-2.39-82.patch b/SOURCES/glibc-upstream-2.39-82.patch
new file mode 100644
index 0000000000000000000000000000000000000000..26e6b1a0d022b765cecbb0546e957474104d1125
--- /dev/null
+++ b/SOURCES/glibc-upstream-2.39-82.patch
@@ -0,0 +1,53 @@
+commit 5c46e6b66636be0010e9a732d5ba1e65ebd54687
+Author: Stefan Liebler <stli@linux.ibm.com>
+Date:   Thu Jul 11 11:28:53 2024 +0200
+
+    s390x: Fix segfault in wcsncmp [BZ #31934]
+    
+    The z13/vector-optimized wcsncmp implementation segfaults if n=1
+    and there is only one character (equal on both strings) before
+    the page end.  Then it loads and compares one character and misses
+    to check n again.  The following load fails.
+    
+    This patch removes the extra load and compare of the first character
+    and just start with the loop which uses vector-load-to-block-boundary.
+    This code-path also checks n.
+    
+    With this patch both tests are passing:
+    - the simplified one mentioned in the bugzilla 31934
+    - the full one in Florian Weimer's patch:
+    "manual: Document a GNU extension for strncmp/wcsncmp"
+    (https://patchwork.sourceware.org/project/glibc/patch/874j9eml6y.fsf@oldenburg.str.redhat.com/):
+    On s390x-linux-gnu (z16), the new wcsncmp test fails due to bug 31934.
+    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+    
+    (cherry picked from commit 9b7651410375ec8848a1944992d663d514db4ba7)
+
+diff --git a/sysdeps/s390/wcsncmp-vx.S b/sysdeps/s390/wcsncmp-vx.S
+index bf6dfa6bc2b904b5..8b081567a2a5732c 100644
+--- a/sysdeps/s390/wcsncmp-vx.S
++++ b/sysdeps/s390/wcsncmp-vx.S
+@@ -59,14 +59,7 @@ ENTRY(WCSNCMP_Z13)
+ 	sllg	%r4,%r4,2	/* Convert character-count to byte-count.  */
+ 	locgrne	%r4,%r1		/* Use max byte-count, if bit 0/1 was one.  */
+ 
+-	/* Check first character without vector load.  */
+-	lghi	%r5,4		/* current_len = 4 bytes.  */
+-	/* Check s1/2[0].  */
+-	lt	%r0,0(%r2)
+-	l	%r1,0(%r3)
+-	je	.Lend_cmp_one_char
+-	crjne	%r0,%r1,.Lend_cmp_one_char
+-
++	lghi	%r5,0		/* current_len = 0 bytes.  */
+ .Lloop:
+ 	vlbb	%v17,0(%r5,%r3),6 /* Load s2 to block boundary.  */
+ 	vlbb	%v16,0(%r5,%r2),6 /* Load s1 to block boundary.  */
+@@ -167,7 +160,6 @@ ENTRY(WCSNCMP_Z13)
+ 	srl	%r4,2		/* And convert it to character-index.  */
+ 	vlgvf	%r0,%v16,0(%r4)	/* Load character-values.  */
+ 	vlgvf	%r1,%v17,0(%r4)
+-.Lend_cmp_one_char:
+ 	cr	%r0,%r1
+ 	je	.Lend_equal
+ 	lghi	%r2,1
diff --git a/SOURCES/glibc-upstream-2.39-83.patch b/SOURCES/glibc-upstream-2.39-83.patch
new file mode 100644
index 0000000000000000000000000000000000000000..6b531dffa188bf27a823cac2942cd83c6b8f61e0
--- /dev/null
+++ b/SOURCES/glibc-upstream-2.39-83.patch
@@ -0,0 +1,153 @@
+commit 1062ebbd1911ec9efe909765ca3ee3809ec3fd67
+Author: Michael Jeanson <mjeanson@efficios.com>
+Date:   Wed Jul 3 12:35:34 2024 -0400
+
+    nptl: fix potential merge of __rseq_* relro symbols
+    
+    While working on a patch to add support for the extensible rseq ABI, we
+    came across an issue where a new 'const' variable would be merged with
+    the existing '__rseq_size' variable. We tracked this to the use of
+    '-fmerge-all-constants' which allows the compiler to merge identical
+    constant variables. This means that all 'const' variables in a compile
+    unit that are of the same size and are initialized to the same value can
+    be merged.
+    
+    In this specific case, on 32 bit systems 'unsigned int' and 'ptrdiff_t'
+    are both 4 bytes and initialized to 0 which should trigger the merge.
+    However for reasons we haven't delved into when the attribute 'section
+    (".data.rel.ro")' is added to the mix, only variables of the same exact
+    types are merged. As far as we know this behavior is not specified
+    anywhere and could change with a new compiler version, hence this patch.
+    
+    Move the definitions of these variables into an assembler file and add
+    hidden writable aliases for internal use. This has the added bonus of
+    removing the asm workaround to set the values on rseq registration.
+    
+    Tested on Debian 12 with GCC 12.2.
+    
+    Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
+    Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+    Reviewed-by: Florian Weimer <fweimer@redhat.com>
+    (cherry picked from commit 2b92982e2369d292560793bee8e730f695f48ff3)
+
+diff --git a/elf/Makefile b/elf/Makefile
+index a50a988e7362cf3b..0049ffa13c8d3e51 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -73,6 +73,7 @@ dl-routines = \
+   dl-origin \
+   dl-printf \
+   dl-reloc \
++  dl-rseq-symbols \
+   dl-runtime \
+   dl-scope \
+   dl-setup_hash \
+diff --git a/elf/dl-rseq-symbols.S b/elf/dl-rseq-symbols.S
+new file mode 100644
+index 0000000000000000..b4bba06a99b0a486
+--- /dev/null
++++ b/elf/dl-rseq-symbols.S
+@@ -0,0 +1,64 @@
++/* Define symbols used by rseq.
++   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 <sysdep.h>
++
++#if __WORDSIZE == 64
++#define RSEQ_OFFSET_SIZE	8
++#else
++#define RSEQ_OFFSET_SIZE	4
++#endif
++
++/* Some targets define a macro to denote the zero register.  */
++#undef zero
++
++/* Define 2 symbols: '__rseq_size' is public const and '_rseq_size' (an
++   alias of '__rseq_size') is hidden and writable for internal use by the
++   dynamic linker which will initialize the value both symbols point to
++   before copy relocations take place. */
++
++	.globl	__rseq_size
++	.type	__rseq_size, %object
++	.size	__rseq_size, 4
++	.hidden _rseq_size
++	.globl	_rseq_size
++	.type	_rseq_size, %object
++	.size	_rseq_size, 4
++	.section .data.rel.ro
++	.balign 4
++__rseq_size:
++_rseq_size:
++	.zero	4
++
++/* Define 2 symbols: '__rseq_offset' is public const and '_rseq_offset' (an
++   alias of '__rseq_offset') is hidden and writable for internal use by the
++   dynamic linker which will initialize the value both symbols point to
++   before copy relocations take place. */
++
++	.globl	__rseq_offset
++	.type	__rseq_offset, %object
++	.size	__rseq_offset, RSEQ_OFFSET_SIZE
++	.hidden _rseq_offset
++	.globl	_rseq_offset
++	.type	_rseq_offset, %object
++	.size	_rseq_offset, RSEQ_OFFSET_SIZE
++	.section .data.rel.ro
++	.balign RSEQ_OFFSET_SIZE
++__rseq_offset:
++_rseq_offset:
++	.zero	RSEQ_OFFSET_SIZE
+diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c
+index 092c274f369dd046..7eb35fb13384f6ac 100644
+--- a/sysdeps/nptl/dl-tls_init_tp.c
++++ b/sysdeps/nptl/dl-tls_init_tp.c
+@@ -45,8 +45,10 @@ rtld_mutex_dummy (pthread_mutex_t *lock)
+ #endif
+ 
+ const unsigned int __rseq_flags;
+-const unsigned int __rseq_size attribute_relro;
+-const ptrdiff_t __rseq_offset attribute_relro;
++
++/* The variables are in .data.relro but are not yet write-protected.  */
++extern unsigned int _rseq_size attribute_hidden;
++extern ptrdiff_t _rseq_offset attribute_hidden;
+ 
+ void
+ __tls_pre_init_tp (void)
+@@ -105,10 +107,7 @@ __tls_init_tp (void)
+     do_rseq = TUNABLE_GET (rseq, int, NULL);
+     if (rseq_register_current_thread (pd, do_rseq))
+       {
+-        /* We need a writable view of the variables.  They are in
+-           .data.relro and are not yet write-protected.  */
+-        extern unsigned int size __asm__ ("__rseq_size");
+-        size = sizeof (pd->rseq_area);
++        _rseq_size = sizeof (pd->rseq_area);
+       }
+ 
+ #ifdef RSEQ_SIG
+@@ -117,8 +116,7 @@ __tls_init_tp (void)
+        all targets support __thread_pointer, so set __rseq_offset only
+        if the rseq registration may have happened because RSEQ_SIG is
+        defined.  */
+-    extern ptrdiff_t offset __asm__ ("__rseq_offset");
+-    offset = (char *) &pd->rseq_area - (char *) __thread_pointer ();
++    _rseq_offset = (char *) &pd->rseq_area - (char *) __thread_pointer ();
+ #endif
+   }
+ 
diff --git a/SOURCES/glibc-upstream-2.39-84.patch b/SOURCES/glibc-upstream-2.39-84.patch
new file mode 100644
index 0000000000000000000000000000000000000000..1e5251c77d255b8ac7f0735c18cc68118abdbe38
--- /dev/null
+++ b/SOURCES/glibc-upstream-2.39-84.patch
@@ -0,0 +1,43 @@
+commit 143a7a06235cf091b63f58a739c8367ffe54a722
+Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date:   Thu Jul 4 10:09:07 2024 -0300
+
+    elf: Make dl-rseq-symbols Linux only
+    
+    And avoid a Hurd build failures.
+    
+    Checked on x86_64-linux-gnu.
+    
+    (cherry picked from commit 9fc639f654dc004736836613be703e6bed0c36a8)
+
+diff --git a/elf/Makefile b/elf/Makefile
+index 0049ffa13c8d3e51..a50a988e7362cf3b 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -73,7 +73,6 @@ dl-routines = \
+   dl-origin \
+   dl-printf \
+   dl-reloc \
+-  dl-rseq-symbols \
+   dl-runtime \
+   dl-scope \
+   dl-setup_hash \
+diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
+index 415aa1f14dd20ba6..6ab9b901234dc72e 100644
+--- a/sysdeps/unix/sysv/linux/Makefile
++++ b/sysdeps/unix/sysv/linux/Makefile
+@@ -615,6 +615,10 @@ tests += \
+ endif
+ 
+ ifeq ($(subdir),elf)
++dl-routines += \
++  dl-rseq-symbols \
++  # dl-routines
++
+ sysdep-rtld-routines += \
+   dl-brk \
+   dl-getcwd \
+diff --git a/elf/dl-rseq-symbols.S b/sysdeps/unix/sysv/linux/dl-rseq-symbols.S
+similarity index 100%
+rename from elf/dl-rseq-symbols.S
+rename to sysdeps/unix/sysv/linux/dl-rseq-symbols.S
diff --git a/SOURCES/glibc-upstream-2.39-85.patch b/SOURCES/glibc-upstream-2.39-85.patch
new file mode 100644
index 0000000000000000000000000000000000000000..eb2394acde9f5b80271a30f041bca2087ca55425
--- /dev/null
+++ b/SOURCES/glibc-upstream-2.39-85.patch
@@ -0,0 +1,137 @@
+commit e8f521709731ce3ae8d6f1eca30135d5c0606f02
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Mon Jul 8 21:14:00 2024 +0200
+
+    Linux: Make __rseq_size useful for feature detection (bug 31965)
+    
+    The __rseq_size value is now the active area of struct rseq
+    (so 20 initially), not the full struct size including padding
+    at the end (32 initially).
+    
+    Update misc/tst-rseq to print some additional diagnostics.
+    
+    Reviewed-by: Michael Jeanson <mjeanson@efficios.com>
+    Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+    (cherry picked from commit 2e456ccf0c34a056e3ccafac4a0c7effef14d918)
+
+diff --git a/manual/threads.texi b/manual/threads.texi
+index e5544ff3da8733f4..25e99c9606dcad77 100644
+--- a/manual/threads.texi
++++ b/manual/threads.texi
+@@ -1007,8 +1007,12 @@ This variable is either zero (if restartable sequence registration
+ failed or has been disabled) or the size of the restartable sequence
+ registration.  This can be different from the size of @code{struct rseq}
+ if the kernel has extended the size of the registration.  If
+-registration is successful, @code{__rseq_size} is at least 32 (the
+-initial size of @code{struct rseq}).
++registration is successful, @code{__rseq_size} is at least 20 (the
++initially active size of @code{struct rseq}).
++
++Previous versions of @theglibc{} set this to 32 even if the kernel only
++supported the initial area of 20 bytes because the value included unused
++padding at the end of the restartable sequence area.
+ @end deftypevar
+ 
+ @deftypevar {unsigned int} __rseq_flags
+diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c
+index 7eb35fb13384f6ac..7803e19fd16ad803 100644
+--- a/sysdeps/nptl/dl-tls_init_tp.c
++++ b/sysdeps/nptl/dl-tls_init_tp.c
+@@ -46,10 +46,6 @@ rtld_mutex_dummy (pthread_mutex_t *lock)
+ 
+ const unsigned int __rseq_flags;
+ 
+-/* The variables are in .data.relro but are not yet write-protected.  */
+-extern unsigned int _rseq_size attribute_hidden;
+-extern ptrdiff_t _rseq_offset attribute_hidden;
+-
+ void
+ __tls_pre_init_tp (void)
+ {
+@@ -106,9 +102,7 @@ __tls_init_tp (void)
+     bool do_rseq = true;
+     do_rseq = TUNABLE_GET (rseq, int, NULL);
+     if (rseq_register_current_thread (pd, do_rseq))
+-      {
+-        _rseq_size = sizeof (pd->rseq_area);
+-      }
++      _rseq_size = RSEQ_AREA_SIZE_INITIAL_USED;
+ 
+ #ifdef RSEQ_SIG
+     /* This should be a compile-time constant, but the current
+diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h
+index 48eebc1e168fad1e..7ea935b4adab8c20 100644
+--- a/sysdeps/unix/sysv/linux/rseq-internal.h
++++ b/sysdeps/unix/sysv/linux/rseq-internal.h
+@@ -25,15 +25,34 @@
+ #include <stdio.h>
+ #include <sys/rseq.h>
+ 
++/* 32 is the initially required value for the area size.  The
++   actually used rseq size may be less (20 bytes initially).  */
++#define RSEQ_AREA_SIZE_INITIAL 32
++#define RSEQ_AREA_SIZE_INITIAL_USED 20
++
++/* The variables are in .data.relro but are not yet write-protected.  */
++extern unsigned int _rseq_size attribute_hidden;
++extern ptrdiff_t _rseq_offset attribute_hidden;
++
+ #ifdef RSEQ_SIG
+ static inline bool
+ rseq_register_current_thread (struct pthread *self, bool do_rseq)
+ {
+   if (do_rseq)
+     {
++      unsigned int size;
++#if IS_IN (rtld)
++      /* Use the hidden symbol in ld.so.  */
++      size = _rseq_size;
++#else
++      size = __rseq_size;
++#endif
++      if (size < RSEQ_AREA_SIZE_INITIAL)
++        /* The initial implementation used only 20 bytes out of 32,
++           but still expected size 32.  */
++        size = RSEQ_AREA_SIZE_INITIAL;
+       int ret = INTERNAL_SYSCALL_CALL (rseq, &self->rseq_area,
+-                                       sizeof (self->rseq_area),
+-                                       0, RSEQ_SIG);
++                                       size, 0, RSEQ_SIG);
+       if (!INTERNAL_SYSCALL_ERROR_P (ret))
+         return true;
+     }
+diff --git a/sysdeps/unix/sysv/linux/tst-rseq.c b/sysdeps/unix/sysv/linux/tst-rseq.c
+index 2c90409ba02182e7..08a95331306b2a12 100644
+--- a/sysdeps/unix/sysv/linux/tst-rseq.c
++++ b/sysdeps/unix/sysv/linux/tst-rseq.c
+@@ -29,6 +29,7 @@
+ # include <stdlib.h>
+ # include <string.h>
+ # include <syscall.h>
++# include <sys/auxv.h>
+ # include <thread_pointer.h>
+ # include <tls.h>
+ # include "tst-rseq.h"
+@@ -42,7 +43,8 @@ do_rseq_main_test (void)
+   TEST_COMPARE (__rseq_flags, 0);
+   TEST_VERIFY ((char *) __thread_pointer () + __rseq_offset
+                == (char *) &pd->rseq_area);
+-  TEST_COMPARE (__rseq_size, sizeof (pd->rseq_area));
++  /* The current implementation only supports the initial size.  */
++  TEST_COMPARE (__rseq_size, 20);
+ }
+ 
+ static void
+@@ -52,6 +54,12 @@ do_rseq_test (void)
+     {
+       FAIL_UNSUPPORTED ("kernel does not support rseq, skipping test");
+     }
++  printf ("info: __rseq_size: %u\n", __rseq_size);
++  printf ("info: __rseq_offset: %td\n", __rseq_offset);
++  printf ("info: __rseq_flags: %u\n", __rseq_flags);
++  printf ("info: getauxval (AT_RSEQ_FEATURE_SIZE): %ld\n",
++          getauxval (AT_RSEQ_FEATURE_SIZE));
++  printf ("info: getauxval (AT_RSEQ_ALIGN): %ld\n", getauxval (AT_RSEQ_ALIGN));
+   do_rseq_main_test ();
+ }
+ #else /* RSEQ_SIG */
diff --git a/SOURCES/glibc-upstream-2.39-86.patch b/SOURCES/glibc-upstream-2.39-86.patch
new file mode 100644
index 0000000000000000000000000000000000000000..b15d1acd04b37f881e4eaabb8732a10a4ccd0184
--- /dev/null
+++ b/SOURCES/glibc-upstream-2.39-86.patch
@@ -0,0 +1,58 @@
+commit f6a75fddf4e71545c63dfcad99cc2df9bac38093
+Author: John David Anglin <danglin@gcc.gnu.org>
+Date:   Fri Jul 19 10:10:17 2024 -0400
+
+    Fix usage of _STACK_GROWS_DOWN and _STACK_GROWS_UP defines [BZ 31989]
+    
+    Signed-off-by: John David Anglin <dave.anglin@bell.net>
+    Reviewed-By: Andreas K. Hüttel <dilfridge@gentoo.org>
+    (cherry picked from commit 8cfa4ecff21adf226984f135aa576dd8063bbba3)
+
+diff --git a/malloc/memusage.c b/malloc/memusage.c
+index e8ae80dc74af4585..f80225b95a36707b 100644
+--- a/malloc/memusage.c
++++ b/malloc/memusage.c
+@@ -172,7 +172,7 @@ update_data (struct header *result, size_t len, size_t old_len)
+     start_sp = __thread_stack_pointer ();
+ 
+   uintptr_t sp = __thread_stack_pointer ();
+-#ifdef _STACK_GROWS_UP
++#if _STACK_GROWS_UP
+   /* This can happen in threads where we didn't catch the thread's
+      stack early enough.  */
+   if (__glibc_unlikely (sp < start_sp))
+diff --git a/stdlib/tst-swapcontext2.c b/stdlib/tst-swapcontext2.c
+index f679755649809653..a9c1dc827cb897f3 100644
+--- a/stdlib/tst-swapcontext2.c
++++ b/stdlib/tst-swapcontext2.c
+@@ -85,7 +85,7 @@ do_test (void)
+ {
+   /* ____longjmp_chk has  */
+ #if 0
+-#ifdef _STACK_GROWS_DOWN
++#if _STACK_GROWS_DOWN
+ #define called_from(this, saved) ((this) < (saved))
+ #else
+ #define called_from(this, saved) ((this) > (saved))
+@@ -98,7 +98,7 @@ do_test (void)
+   /* Arrange stacks for uctx_func1 and uctx_func2 so that called_from
+      is true when setjmp is called from uctx_func1 and longjmp is called
+      from uctx_func2.  */
+-#ifdef _STACK_GROWS_DOWN
++#if _STACK_GROWS_DOWN
+ # define UCTX_FUNC1_STACK	1
+ # define UCTX_FUNC2_STACK	0
+ #else
+diff --git a/sysdeps/unix/sysv/linux/____longjmp_chk.c b/sysdeps/unix/sysv/linux/____longjmp_chk.c
+index 0896dc5755dfa1db..3c66a4638eedbbea 100644
+--- a/sysdeps/unix/sysv/linux/____longjmp_chk.c
++++ b/sysdeps/unix/sysv/linux/____longjmp_chk.c
+@@ -23,7 +23,7 @@
+ #include <stdio.h>
+ #include <stackinfo.h>
+ 
+-#ifdef _STACK_GROWS_DOWN
++#if _STACK_GROWS_DOWN
+ #define called_from(this, saved) ((this) < (saved))
+ #else
+ #define called_from(this, saved) ((this) > (saved))
diff --git a/SOURCES/glibc-upstream-2.39-87.patch b/SOURCES/glibc-upstream-2.39-87.patch
new file mode 100644
index 0000000000000000000000000000000000000000..311203b8aedd08079a603145bed6190c19c8637a
--- /dev/null
+++ b/SOURCES/glibc-upstream-2.39-87.patch
@@ -0,0 +1,81 @@
+commit cb19cef087eaa551568739aa5b59cf97b8d5da1e
+Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date:   Tue Jul 16 07:57:45 2024 -0300
+
+    elf: Fix localplt.awk for DT_RELR-enabled builds (BZ 31978)
+    
+    For each input readelf output, localplt.awk parses each 'Relocation
+    section' entry, checks its offset against the dynamic section entry, and
+    saves each DT_JMPREL, DT_RELA, and DT_REL offset value it finds. After
+    all lines are read, the script checks if any segment offset differed
+    from 0, meaning at least one 'Relocation section' was matched.
+    
+    However, if the shared object was built with RELR support and the static
+    linker could place all the relocation on DT_RELR, there would be no
+    DT_JMPREL, DT_RELA, and DT_REL entries; only a DT_RELR.
+    
+    For the current three ABIs that support (aarch64, x86, and powerpc64),
+    the powerpc64 ld.so shows the behavior above. Both x86_64 and aarch64
+    show extra relocations on '.rela.dyn', which makes the script check to
+    succeed.
+    
+    This patch fixes by handling DT_RELR, where the offset is checked
+    against the dynamic section entries and if the shared object contains an
+    entry it means that there are no extra PLT entries (since all
+    relocations are relative).
+    
+    It fixes the elf/check-localplt failure on powerpc.
+    
+    Checked with a build/check for aarch64-linux-gnu, x86_64-linux-gnu,
+    i686-linux-gnu, arm-linux-gnueabihf, s390x-linux-gnu, powerpc-linux-gnu,
+    powerpc64-linux-gnu, and powerpc64le-linux-gnu.
+    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+    
+    (cherry picked from commit 4f047d9edecb1a9b796a9a904dcd42bd3cc3d3b6)
+
+diff --git a/scripts/localplt.awk b/scripts/localplt.awk
+index fe79ca01abcb1a75..621ae7d8e815a4e5 100644
+--- a/scripts/localplt.awk
++++ b/scripts/localplt.awk
+@@ -10,7 +10,8 @@ BEGIN {
+ }
+ 
+ FILENAME != lastfile {
+-  if (lastfile && jmprel_offset == 0 && rela_offset == 0 && rel_offset == 0) {
++  if (lastfile && jmprel_offset == 0 && rela_offset == 0 && rel_offset == 0 \
++      && relr_offset == 0) {
+     print FILENAME ": *** failed to find expected output (readelf -WSdr)";
+     result = 2;
+   }
+@@ -22,6 +23,7 @@ FILENAME != lastfile {
+   jmprel_offset = 0;
+   rela_offset = 0;
+   rel_offset = 0;
++  relr_offset = 0;
+   pltrelsz = -1;
+   delete section_offset_by_address;
+ }
+@@ -77,6 +79,8 @@ in_relocs && relocs_offset == rel_offset && NF >= 5 {
+   }
+ }
+ 
++# No need to handle DT_RELR (all packed relocations are relative).
++
+ in_relocs { next }
+ 
+ $1 == "Relocation" && $2 == "section" && $5 == "offset" {
+@@ -121,4 +125,14 @@ $2 == "(REL)" {
+   }
+   next
+ }
++
++$2 == "(RELR)" {
++  relr_addr = strtonum($3);
++  if (relr_addr in section_offset_by_address) {
++    relr_offset = section_offset_by_address[relr_addr];
++  } else {
++    print FILENAME ": *** DT_RELR does not match any section's address";
++    result = 2;
++  }
++}
+ END { exit(result) }
diff --git a/SOURCES/glibc-upstream-2.39-88.patch b/SOURCES/glibc-upstream-2.39-88.patch
new file mode 100644
index 0000000000000000000000000000000000000000..1afdee1b2d28da7e3c5accb379a984783e6322ce
--- /dev/null
+++ b/SOURCES/glibc-upstream-2.39-88.patch
@@ -0,0 +1,201 @@
+commit fc1dc399841051862a93ed458897e3d8ea9d4ff4
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Wed Jul 24 12:06:47 2024 +0200
+
+    resolv: Allow short error responses to match any query (bug 31890)
+    
+    Reviewed-by: DJ Delorie <dj@redhat.com>
+    (cherry picked from commit 691a3b2e9bfaba842e46a5ccb7f5e6ea144c3ade)
+
+diff --git a/resolv/Makefile b/resolv/Makefile
+index 5f44f5896bde9958..d927e337d9e2b496 100644
+--- a/resolv/Makefile
++++ b/resolv/Makefile
+@@ -106,6 +106,7 @@ tests += \
+   tst-resolv-nondecimal \
+   tst-resolv-res_init-multi \
+   tst-resolv-search \
++  tst-resolv-short-response \
+   tst-resolv-trailing \
+ 
+ # This test calls __res_context_send directly, which is not exported
+@@ -299,6 +300,8 @@ $(objpfx)tst-resolv-nondecimal: $(objpfx)libresolv.so $(shared-thread-library)
+ $(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
+ $(objpfx)tst-resolv-rotate: $(objpfx)libresolv.so $(shared-thread-library)
+ $(objpfx)tst-resolv-search: $(objpfx)libresolv.so $(shared-thread-library)
++$(objpfx)tst-resolv-short-response: $(objpfx)libresolv.so \
++  $(shared-thread-library)
+ $(objpfx)tst-resolv-trailing: $(objpfx)libresolv.so $(shared-thread-library)
+ $(objpfx)tst-resolv-threads: $(objpfx)libresolv.so $(shared-thread-library)
+ $(objpfx)tst-resolv-txnid-collision: $(objpfx)libresolv.a \
+diff --git a/resolv/res_send.c b/resolv/res_send.c
+index fb0217204a6c913f..cef606a6b1523224 100644
+--- a/resolv/res_send.c
++++ b/resolv/res_send.c
+@@ -1197,19 +1197,30 @@ send_dg(res_state statp,
+ 		}
+ 
+ 		/* Check for the correct header layout and a matching
+-		   question.  */
++		   question.  Some recursive resolvers send REFUSED
++		   without copying back the question section
++		   (producing a response that is only HFIXEDSZ bytes
++		   long).  Skip query matching in this case.  */
++		bool thisansp_error = (anhp->rcode == SERVFAIL ||
++				       anhp->rcode == NOTIMP ||
++				       anhp->rcode == REFUSED);
++		bool skip_query_match = (*thisresplenp == HFIXEDSZ
++					 && ntohs (anhp->qdcount) == 0
++					 && thisansp_error);
+ 		int matching_query = 0; /* Default to no matching query.  */
+ 		if (!recvresp1
+ 		    && anhp->id == hp->id
+-		    && __libc_res_queriesmatch (buf, buf + buflen,
+-						*thisansp,
+-						*thisansp + *thisanssizp))
++		    && (skip_query_match
++			|| __libc_res_queriesmatch (buf, buf + buflen,
++						    *thisansp,
++						    *thisansp + *thisanssizp)))
+ 		  matching_query = 1;
+ 		if (!recvresp2
+ 		    && anhp->id == hp2->id
+-		    && __libc_res_queriesmatch (buf2, buf2 + buflen2,
+-						*thisansp,
+-						*thisansp + *thisanssizp))
++		    && (skip_query_match
++			|| __libc_res_queriesmatch (buf2, buf2 + buflen2,
++						    *thisansp,
++						    *thisansp + *thisanssizp)))
+ 		  matching_query = 2;
+ 		if (matching_query == 0)
+ 		  /* Spurious UDP packet.  Drop it and continue
+@@ -1219,9 +1230,7 @@ send_dg(res_state statp,
+ 		    goto wait;
+ 		  }
+ 
+-		if (anhp->rcode == SERVFAIL ||
+-		    anhp->rcode == NOTIMP ||
+-		    anhp->rcode == REFUSED) {
++		if (thisansp_error) {
+ 		next_ns:
+ 			if (recvresp1 || (buf2 != NULL && recvresp2)) {
+ 			  *resplen2 = 0;
+diff --git a/resolv/tst-resolv-short-response.c b/resolv/tst-resolv-short-response.c
+new file mode 100644
+index 0000000000000000..cf1e39876f8fb470
+--- /dev/null
++++ b/resolv/tst-resolv-short-response.c
+@@ -0,0 +1,112 @@
++/* Test for spurious timeouts with short 12-byte responses (bug 31890).
++   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 <resolv.h>
++#include <support/check.h>
++#include <support/resolv_test.h>
++#include <support/check_nss.h>
++
++/* The rcode in the initial response.  */
++static volatile int rcode;
++
++static void
++response (const struct resolv_response_context *ctx,
++          struct resolv_response_builder *b,
++          const char *qname, uint16_t qclass, uint16_t qtype)
++{
++  switch (ctx->server_index)
++    {
++    case 0:
++      /* First server times out.  */
++      struct resolv_response_flags flags = {.rcode = rcode};
++      resolv_response_init (b, flags);
++      break;
++    case 1:
++      /* Second server sends reply.  */
++      resolv_response_init (b, (struct resolv_response_flags) {});
++      resolv_response_add_question (b, qname, qclass, qtype);
++      resolv_response_section (b, ns_s_an);
++      resolv_response_open_record (b, qname, qclass, qtype, 0);
++      switch (qtype)
++        {
++        case T_A:
++          {
++            char ipv4[4] = {192, 0, 2, 17};
++            resolv_response_add_data (b, &ipv4, sizeof (ipv4));
++          }
++          break;
++        case T_AAAA:
++          {
++            char ipv6[16]
++              = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
++            resolv_response_add_data (b, &ipv6, sizeof (ipv6));
++          }
++          break;
++        default:
++          FAIL_EXIT1 ("unexpected TYPE%d query", qtype);
++        }
++      resolv_response_close_record (b);
++      break;
++    default:
++      FAIL_EXIT1 ("unexpected query to server %d", ctx->server_index);
++    }
++}
++
++static void
++check_one (void)
++{
++
++  /* The buggy 1-second query timeout results in 30 seconds of delay,
++     which triggers a test timeout failure.  */
++  for (int i = 0;  i < 10; ++i)
++    {
++      check_hostent ("www.example", gethostbyname ("www.example"),
++                     "name: www.example\n"
++                     "address: 192.0.2.17\n");
++      check_hostent ("www.example", gethostbyname2 ("www.example", AF_INET6),
++                     "name: www.example\n"
++                     "address: 2001:db8::1\n");
++    }
++}
++
++static int
++do_test (void)
++{
++  struct resolv_test *aux = resolv_test_start
++    ((struct resolv_redirect_config)
++     {
++       .response_callback = response,
++     });
++
++  _res.options |= RES_SNGLKUP;
++
++  rcode = 2; /* SERVFAIL.  */
++  check_one ();
++
++  rcode = 4; /* NOTIMP.  */
++  check_one ();
++
++  rcode = 5; /* REFUSED.  */
++  check_one ();
++
++  resolv_test_end (aux);
++
++  return 0;
++}
++
++#include <support/test-driver.c>
diff --git a/SOURCES/glibc-upstream-2.39-89.patch b/SOURCES/glibc-upstream-2.39-89.patch
new file mode 100644
index 0000000000000000000000000000000000000000..a6c7115b4e0b7aafb6f16d32e5cac344d7b2d1bb
--- /dev/null
+++ b/SOURCES/glibc-upstream-2.39-89.patch
@@ -0,0 +1,209 @@
+commit 8c9fbc6651b992e759f6f0b4af21c1a8769bbb2c
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Wed Jul 24 12:06:47 2024 +0200
+
+    resolv: Do not wait for non-existing second DNS response after error (bug 30081)
+    
+    In single-request mode, there is no second response after an error
+    because the second query has not been sent yet.  Waiting for it
+    introduces an unnecessary timeout.
+    
+    Reviewed-by: DJ Delorie <dj@redhat.com>
+    (cherry picked from commit af625987d619388a100b153520d3ee308bda9889)
+
+diff --git a/resolv/Makefile b/resolv/Makefile
+index d927e337d9e2b496..abff7fc0074e893b 100644
+--- a/resolv/Makefile
++++ b/resolv/Makefile
+@@ -106,6 +106,7 @@ tests += \
+   tst-resolv-nondecimal \
+   tst-resolv-res_init-multi \
+   tst-resolv-search \
++  tst-resolv-semi-failure \
+   tst-resolv-short-response \
+   tst-resolv-trailing \
+ 
+@@ -300,6 +301,8 @@ $(objpfx)tst-resolv-nondecimal: $(objpfx)libresolv.so $(shared-thread-library)
+ $(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
+ $(objpfx)tst-resolv-rotate: $(objpfx)libresolv.so $(shared-thread-library)
+ $(objpfx)tst-resolv-search: $(objpfx)libresolv.so $(shared-thread-library)
++$(objpfx)tst-resolv-semi-failure: $(objpfx)libresolv.so \
++  $(shared-thread-library)
+ $(objpfx)tst-resolv-short-response: $(objpfx)libresolv.so \
+   $(shared-thread-library)
+ $(objpfx)tst-resolv-trailing: $(objpfx)libresolv.so $(shared-thread-library)
+diff --git a/resolv/res_send.c b/resolv/res_send.c
+index cef606a6b1523224..3a4a20684fcb9a63 100644
+--- a/resolv/res_send.c
++++ b/resolv/res_send.c
+@@ -1236,7 +1236,7 @@ send_dg(res_state statp,
+ 			  *resplen2 = 0;
+ 			  return resplen;
+ 			}
+-			if (buf2 != NULL)
++			if (buf2 != NULL && !single_request)
+ 			  {
+ 			    /* No data from the first reply.  */
+ 			    resplen = 0;
+diff --git a/resolv/tst-resolv-semi-failure.c b/resolv/tst-resolv-semi-failure.c
+new file mode 100644
+index 0000000000000000..aa9798b5a7dfaa88
+--- /dev/null
++++ b/resolv/tst-resolv-semi-failure.c
+@@ -0,0 +1,133 @@
++/* Test parallel failure/success responses (bug 30081).
++   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 <resolv.h>
++#include <support/check.h>
++#include <support/resolv_test.h>
++#include <support/check_nss.h>
++
++/* The rcode in the initial response.  */
++static volatile int rcode;
++
++/* Whether to fail the initial A query (!fail_aaaa) or the initial
++   AAAA query (fail_aaaa).  */
++static volatile bool fail_aaaa;
++
++static void
++response (const struct resolv_response_context *ctx,
++          struct resolv_response_builder *b,
++          const char *qname, uint16_t qclass, uint16_t qtype)
++{
++  /* Handle the failing query.  */
++  if ((fail_aaaa && qtype == T_AAAA) && ctx->server_index == 0)
++    {
++      struct resolv_response_flags flags = {.rcode = rcode};
++      resolv_response_init (b, flags);
++      return;
++    }
++
++  /* Otherwise produce a response.  */
++  resolv_response_init (b, (struct resolv_response_flags) {});
++  resolv_response_add_question (b, qname, qclass, qtype);
++  resolv_response_section (b, ns_s_an);
++  resolv_response_open_record (b, qname, qclass, qtype, 0);
++  switch (qtype)
++    {
++    case T_A:
++      {
++        char ipv4[4] = {192, 0, 2, 17};
++        resolv_response_add_data (b, &ipv4, sizeof (ipv4));
++      }
++      break;
++    case T_AAAA:
++      {
++        char ipv6[16]
++          = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
++        resolv_response_add_data (b, &ipv6, sizeof (ipv6));
++      }
++      break;
++    default:
++      FAIL_EXIT1 ("unexpected TYPE%d query", qtype);
++    }
++  resolv_response_close_record (b);
++}
++
++static void
++check_one (void)
++{
++
++  /* The buggy 1-second query timeout results in 30 seconds of delay,
++     which triggers are test timeout failure.  */
++  for (int i = 0;  i < 30; ++i)
++    {
++      static const struct addrinfo hints =
++        {
++          .ai_family = AF_UNSPEC,
++          .ai_socktype = SOCK_STREAM,
++        };
++      struct addrinfo *ai;
++      int ret = getaddrinfo ("www.example", "80", &hints, &ai);
++      const char *expected;
++      if (ret == 0 && ai->ai_next != NULL)
++        expected = ("address: STREAM/TCP 192.0.2.17 80\n"
++                    "address: STREAM/TCP 2001:db8::1 80\n");
++      else
++        /* Only one response because the AAAA lookup failure is
++           treated as an ignoreable error.  */
++        expected = "address: STREAM/TCP 192.0.2.17 80\n";
++      check_addrinfo ("www.example", ai, ret, expected);
++      if (ret == 0)
++        freeaddrinfo (ai);
++    }
++}
++
++static int
++do_test (void)
++{
++  for (int do_single_lookup = 0; do_single_lookup < 2; ++do_single_lookup)
++    {
++      struct resolv_test *aux = resolv_test_start
++        ((struct resolv_redirect_config)
++         {
++           .response_callback = response,
++         });
++
++      if (do_single_lookup)
++        _res.options |= RES_SNGLKUP;
++
++      for (int do_fail_aaaa = 0; do_fail_aaaa < 2; ++do_fail_aaaa)
++        {
++          fail_aaaa = do_fail_aaaa;
++
++          rcode = 2; /* SERVFAIL.  */
++          check_one ();
++
++          rcode = 4; /* NOTIMP.  */
++          check_one ();
++
++          rcode = 5; /* REFUSED.  */
++          check_one ();
++        }
++
++      resolv_test_end (aux);
++    }
++
++  return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/resolv/tst-resolv-short-response.c b/resolv/tst-resolv-short-response.c
+index cf1e39876f8fb470..be354ae1c7f2a81a 100644
+--- a/resolv/tst-resolv-short-response.c
++++ b/resolv/tst-resolv-short-response.c
+@@ -81,6 +81,18 @@ check_one (void)
+       check_hostent ("www.example", gethostbyname2 ("www.example", AF_INET6),
+                      "name: www.example\n"
+                      "address: 2001:db8::1\n");
++      static const struct addrinfo hints =
++        {
++          .ai_family = AF_UNSPEC,
++          .ai_socktype = SOCK_STREAM,
++        };
++      struct addrinfo *ai;
++      int ret = getaddrinfo ("www.example", "80", &hints, &ai);
++      check_addrinfo ("www.example", ai, ret,
++                      "address: STREAM/TCP 192.0.2.17 80\n"
++                      "address: STREAM/TCP 2001:db8::1 80\n");
++      if (ret == 0)
++        freeaddrinfo (ai);
+     }
+ }
+ 
diff --git a/SOURCES/glibc-upstream-2.39-90.patch b/SOURCES/glibc-upstream-2.39-90.patch
new file mode 100644
index 0000000000000000000000000000000000000000..2c61b362a25f07a73b6238bdb760f376fafe4edc
--- /dev/null
+++ b/SOURCES/glibc-upstream-2.39-90.patch
@@ -0,0 +1,61 @@
+commit 51db012c9408d0ae08ea5f6dd8e663fb3a5a5dfd
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Thu Jun 13 18:56:30 2024 +0200
+
+    resolv: Track single-request fallback via _res._flags (bug 31476)
+    
+    This avoids changing _res.options, which inteferes with change
+    detection as part of automatic reloading of /etc/resolv.conf.
+    
+    Reviewed-by: DJ Delorie <dj@redhat.com>
+    (cherry picked from commit 868ab8923a2ec977faafec97ecafac0c3159c1b2)
+
+diff --git a/resolv/res_send.c b/resolv/res_send.c
+index 3a4a20684fcb9a63..9c77613f374e5469 100644
+--- a/resolv/res_send.c
++++ b/resolv/res_send.c
+@@ -947,9 +947,11 @@ send_dg(res_state statp,
+ 		seconds /= statp->nscount;
+ 	if (seconds <= 0)
+ 		seconds = 1;
+-	bool single_request_reopen = (statp->options & RES_SNGLKUPREOP) != 0;
+-	bool single_request = (((statp->options & RES_SNGLKUP) != 0)
+-			       | single_request_reopen);
++	bool single_request_reopen = ((statp->options & RES_SNGLKUPREOP)
++				      || (statp->_flags & RES_F_SNGLKUPREOP));
++	bool single_request = ((statp->options & RES_SNGLKUP)
++			       || (statp->_flags & RES_F_SNGLKUP)
++			       || single_request_reopen);
+ 	int save_gotsomewhere = *gotsomewhere;
+ 
+ 	int retval;
+@@ -1006,14 +1008,14 @@ send_dg(res_state statp,
+ 		       have received the first answer.  */
+ 		    if (!single_request)
+ 		      {
+-			statp->options |= RES_SNGLKUP;
++			statp->_flags |= RES_F_SNGLKUP;
+ 			single_request = true;
+ 			*gotsomewhere = save_gotsomewhere;
+ 			goto retry;
+ 		      }
+ 		    else if (!single_request_reopen)
+ 		      {
+-			statp->options |= RES_SNGLKUPREOP;
++			statp->_flags |= RES_F_SNGLKUPREOP;
+ 			single_request_reopen = true;
+ 			*gotsomewhere = save_gotsomewhere;
+ 			__res_iclose (statp, false);
+diff --git a/resolv/resolv-internal.h b/resolv/resolv-internal.h
+index 24b164f6b5df4c99..944af3ee7613b3c4 100644
+--- a/resolv/resolv-internal.h
++++ b/resolv/resolv-internal.h
+@@ -26,6 +26,8 @@
+ #define RES_F_VC        0x00000001 /* Socket is TCP.  */
+ #define RES_F_CONN      0x00000002 /* Socket is connected.  */
+ #define RES_F_EDNS0ERR  0x00000004 /* EDNS0 caused errors.  */
++#define RES_F_SNGLKUP	0x00200000 /* Private version of RES_SNGLKUP.  */
++#define RES_F_SNGLKUPREOP 0x00400000 /* Private version of RES_SNGLKUPREOP.  */
+ 
+ /* The structure HEADER is normally aligned on a word boundary.  In
+    some code, we need to access this structure when it may be aligned
diff --git a/SOURCES/glibc-upstream-2.39-91.patch b/SOURCES/glibc-upstream-2.39-91.patch
new file mode 100644
index 0000000000000000000000000000000000000000..bc0c1a3f8446d4abef25577ddb11bd35ac5489f8
--- /dev/null
+++ b/SOURCES/glibc-upstream-2.39-91.patch
@@ -0,0 +1,88 @@
+commit f11b7178a12be4f26fef157cdee7bf6a944693d9
+Author: Miguel Martín <mmartinv@redhat.com>
+Date:   Tue Jul 16 17:14:56 2024 +0200
+
+    malloc: avoid global locks in tst-aligned_alloc-lib.c
+    
+    Make sure the DSO used by aligned_alloc/calloc/malloc tests does not get
+    a global lock on multithreaded tests.
+    Reviewed-by: Arjun Shankar <arjun@redhat.com>
+    
+    (cherry picked from commit 9a27b566b2048f599048f2f4afe1cce06c4ef43d)
+
+diff --git a/malloc/tst-aligned_alloc-lib.c b/malloc/tst-aligned_alloc-lib.c
+index 0205df5acf6297a5..9ef1f839c101a6ae 100644
+--- a/malloc/tst-aligned_alloc-lib.c
++++ b/malloc/tst-aligned_alloc-lib.c
+@@ -17,37 +17,38 @@
+    License along with the GNU C Library; see the file COPYING.LIB.  If
+    not, see <https://www.gnu.org/licenses/>.  */
+ 
+-#include <array_length.h>
+ #include <libc-symbols.h>
+ #include <stdlib.h>
++#include <time.h>
+ 
+ extern void *__libc_malloc (size_t size);
+ extern void *__libc_calloc (size_t n, size_t size);
+ 
++__thread unsigned int seed = 0;
++
+ int aligned_alloc_count = 0;
+ int libc_malloc_count = 0;
+ int libc_calloc_count = 0;
+ 
+-/* Get a random alignment value.  Biased towards the smaller values.  Must be
+-   a power of 2. */
+-static size_t get_random_alignment (void)
+-{
+-  size_t aligns[] = {
+-    1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384
+-  };
+-
+-  return aligns[random () % array_length (aligns)];
+-}
+-
+-static void *get_random_alloc (size_t size)
++static void *
++get_random_alloc (size_t size)
+ {
+   void *retval;
+   size_t align;
++  struct timespec tp;
++
++  if (seed == 0)
++    {
++      clock_gettime (CLOCK_REALTIME, &tp);
++      seed = tp.tv_nsec;
++    }
+ 
+-  switch (random() % 3)
+-  {
++  switch (rand_r (&seed) % 3)
++    {
+     case 1:
+-      align = get_random_alignment ();
++      /* Get a random alignment value.  Biased towards the smaller
++       * values up to 16384. Must be a power of 2. */
++      align = 1 << rand_r (&seed) % 15;
+       retval = aligned_alloc (align, size);
+       aligned_alloc_count++;
+       break;
+@@ -59,13 +60,13 @@ static void *get_random_alloc (size_t size)
+       retval = __libc_malloc (size);
+       libc_malloc_count++;
+       break;
+-  }
++    }
+ 
+   return retval;
+ }
+ 
+-
+-void * __random_malloc (size_t size)
++void *
++__random_malloc (size_t size)
+ {
+   return get_random_alloc (size);
+ }
diff --git a/SOURCES/glibc-upstream-2.39-92.patch b/SOURCES/glibc-upstream-2.39-92.patch
new file mode 100644
index 0000000000000000000000000000000000000000..1847f4fbae491d6ef2dc2e32c6f8ab3ba85ba652
--- /dev/null
+++ b/SOURCES/glibc-upstream-2.39-92.patch
@@ -0,0 +1,247 @@
+commit 946006d37cfc66c162877fc678405525a50f20df
+Author: Miguel Martín <mmartinv@redhat.com>
+Date:   Tue Jul 16 17:14:57 2024 +0200
+
+    malloc: add multi-threaded tests for aligned_alloc/calloc/malloc
+    
+    Improve aligned_alloc/calloc/malloc test coverage by adding
+    multi-threaded tests with random memory allocations and with/without
+    cross-thread memory deallocations.
+    
+    Perform a number of memory allocation calls with random sizes limited
+    to 0xffff.
+    
+    Use the existing DSO ('malloc/tst-aligned_alloc-lib.c') to randomize
+    allocator selection.
+    
+    The multi-threaded allocation/deallocation is staged as described below:
+    
+    - Stage 1: Half of the threads will be allocating memory and the
+      other half will be waiting for them to finish the allocation.
+    - Stage 2: Half of the threads will be allocating memory and the
+      other half will be deallocating memory.
+    - Stage 3: Half of the threads will be deallocating memory and the
+      second half waiting on them to finish.
+    
+    Add 'malloc/tst-aligned-alloc-random-thread.c' where each thread will
+    deallocate only the memory that was previously allocated by itself.
+    
+    Add 'malloc/tst-aligned-alloc-random-thread-cross.c' where each thread
+    will deallocate memory that was previously allocated by another thread.
+    
+    The intention is to be able to utilize existing malloc testing to ensure
+    that similar allocation APIs are also exposed to the same rigors.
+    Reviewed-by: Arjun Shankar <arjun@redhat.com>
+    
+    (cherry picked from commit b0fbcb7d0051a68baf26b2aed51a8a31c34d68e5)
+
+diff --git a/malloc/Makefile b/malloc/Makefile
+index 02aff1bd1dc664c3..98d507a6eb61f4fe 100644
+--- a/malloc/Makefile
++++ b/malloc/Makefile
+@@ -28,6 +28,8 @@ tests := \
+   mallocbug \
+   tst-aligned-alloc \
+   tst-aligned-alloc-random \
++  tst-aligned-alloc-random-thread \
++  tst-aligned-alloc-random-thread-cross \
+   tst-alloc_buffer \
+   tst-calloc \
+   tst-free-errno \
+@@ -151,6 +153,8 @@ ifeq ($(have-GLIBC_2.23)$(build-shared),yesyes)
+ # the tests expect specific internal behavior that is changed due to linking to
+ # libmcheck.a.
+ tests-exclude-mcheck = \
++  tst-aligned-alloc-random-thread \
++  tst-aligned-alloc-random-thread-cross \
+   tst-compathooks-off \
+   tst-compathooks-on \
+   tst-malloc-backtrace \
+@@ -415,7 +419,11 @@ $(objpfx)tst-mallocstate: $(objpfx)libc_malloc_debug.so
+ $(objpfx)tst-mallocstate-malloc-check: $(objpfx)libc_malloc_debug.so
+ 
+ $(objpfx)tst-aligned-alloc-random.out: $(objpfx)tst-aligned_alloc-lib.so
++$(objpfx)tst-aligned-alloc-random-thread.out: $(objpfx)tst-aligned_alloc-lib.so
++$(objpfx)tst-aligned-alloc-random-thread-cross.out: $(objpfx)tst-aligned_alloc-lib.so
+ $(objpfx)tst-malloc-random.out: $(objpfx)tst-aligned_alloc-lib.so
+ 
+ tst-aligned-alloc-random-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
++tst-aligned-alloc-random-thread-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
++tst-aligned-alloc-random-thread-cross-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
+ tst-malloc-random-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
+diff --git a/malloc/tst-aligned-alloc-random-thread-cross.c b/malloc/tst-aligned-alloc-random-thread-cross.c
+new file mode 100644
+index 0000000000000000..360ecc56ee7c8c06
+--- /dev/null
++++ b/malloc/tst-aligned-alloc-random-thread-cross.c
+@@ -0,0 +1,19 @@
++/* multi-threaded memory allocation and cross-thread deallocation test.
++   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; see the file COPYING.LIB.  If
++   not, see <https://www.gnu.org/licenses/>.  */
++#define CROSS_THREAD_DEALLOC
++#include "tst-aligned-alloc-random-thread.c"
+diff --git a/malloc/tst-aligned-alloc-random-thread.c b/malloc/tst-aligned-alloc-random-thread.c
+new file mode 100644
+index 0000000000000000..e95f79250abec85e
+--- /dev/null
++++ b/malloc/tst-aligned-alloc-random-thread.c
+@@ -0,0 +1,145 @@
++/* multi-threaded memory allocation/deallocation test.
++   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; see the file COPYING.LIB.  If
++   not, see <https://www.gnu.org/licenses/>.  */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <support/check.h>
++#include <support/support.h>
++#include <support/xthread.h>
++#include <support/test-driver.h>
++#include <sys/sysinfo.h>
++#include <unistd.h>
++
++#ifndef ITERATIONS
++#  define ITERATIONS 16
++#endif
++
++#ifndef NUM_THREADS
++#  define NUM_THREADS 8
++#endif
++
++#ifndef NUM_ALLOCATIONS
++#  define NUM_ALLOCATIONS 2048
++#endif
++
++static pthread_barrier_t barrier;
++
++__thread unsigned int seed;
++
++typedef struct
++{
++  int id;
++  pthread_t thread;
++} thread;
++
++thread threads[NUM_THREADS];
++
++void *allocations[NUM_THREADS][NUM_ALLOCATIONS];
++
++void
++run_thread_dealloc (int id)
++{
++  for (int i = 0; i < NUM_ALLOCATIONS; i++)
++    {
++      free (allocations[id][i]);
++      allocations[id][i] = NULL;
++    }
++}
++
++void
++run_thread_alloc (int id)
++{
++  size_t msb, size;
++  for (int i = 0; i < NUM_ALLOCATIONS; i++)
++    {
++      msb = 1 << rand_r (&seed) % 16;
++      size = msb + rand_r (&seed) % msb;
++      allocations[id][i] = malloc (size);
++      TEST_VERIFY_EXIT (allocations[id][i] != NULL);
++    }
++}
++
++void *
++run_allocations (void *arg)
++{
++  int id = *((int *) arg);
++  seed = time (NULL) + id;
++
++  /* Stage 1: First half o the threads allocating memory and the second
++   * half waiting for them to finish
++   */
++  if (id < NUM_THREADS / 2)
++    run_thread_alloc (id);
++
++  xpthread_barrier_wait (&barrier);
++
++  /* Stage 2: Half of the threads allocationg memory and the other
++   * half deallocating:
++   * - In the non cross-thread dealloc scenario the first half will be
++   *   deallocating the memory allocated by themselves in stage 1 and the
++   *   second half will be allocating memory.
++   * - In the cross-thread dealloc scenario the first half will continue
++   *   to allocate memory and the second half will deallocate the memory
++   *   allocated by the first half in stage 1.
++   */
++  if (id < NUM_THREADS / 2)
++#ifndef CROSS_THREAD_DEALLOC
++    run_thread_dealloc (id);
++#else
++    run_thread_alloc (id + NUM_THREADS / 2);
++#endif
++  else
++#ifndef CROSS_THREAD_DEALLOC
++    run_thread_alloc (id);
++#else
++    run_thread_dealloc (id - NUM_THREADS / 2);
++#endif
++
++  xpthread_barrier_wait (&barrier);
++
++  // Stage 3: Second half of the threads deallocating and the first half
++  // waiting for them to finish.
++  if (id >= NUM_THREADS / 2)
++    run_thread_dealloc (id);
++
++  return NULL;
++}
++
++static int
++do_test (void)
++{
++  xpthread_barrier_init (&barrier, NULL, NUM_THREADS);
++
++  for (int i = 0; i < ITERATIONS; i++)
++    {
++      for (int t = 0; t < NUM_THREADS; t++)
++	{
++	  threads[t].id = t;
++	  threads[t].thread
++	      = xpthread_create (NULL, run_allocations, &threads[t].id);
++	}
++
++      for (int t = 0; t < NUM_THREADS; t++)
++	xpthread_join (threads[t].thread);
++    }
++
++  return 0;
++}
++
++#include <support/test-driver.c>
diff --git a/SOURCES/glibc-upstream-2.39-93.patch b/SOURCES/glibc-upstream-2.39-93.patch
new file mode 100644
index 0000000000000000000000000000000000000000..b78c6750eddd33a42eda5f193755b2e605dba17e
--- /dev/null
+++ b/SOURCES/glibc-upstream-2.39-93.patch
@@ -0,0 +1,52 @@
+commit b71a51189d3e1a2f515d93c0444916293bd5221f
+Author: Arjun Shankar <arjun@redhat.com>
+Date:   Mon Jul 29 14:30:59 2024 +0200
+
+    manual/stdio: Clarify putc and putwc
+    
+    The manual entry for `putc' described what "most systems" do instead of
+    describing the glibc implementation and its guarantees.  This commit
+    fixes that by warning that putc may be implemented as a macro that
+    double-evaluates `stream', and removing the performance claim.
+    
+    Even though the current `putc' implementation does not double-evaluate
+    `stream', offering this obscure guarantee as an extension to what
+    POSIX allows does not seem very useful.
+    
+    The entry for `putwc' is also edited to bring it in line with `putc'.
+    Reviewed-by: Florian Weimer <fweimer@redhat.com>
+    
+    (cherry picked from commit 10de4a47ef3f481592e3c62eb07bcda23e9fde4d)
+
+diff --git a/manual/stdio.texi b/manual/stdio.texi
+index 002fce7a10e97107..c11d37b363385531 100644
+--- a/manual/stdio.texi
++++ b/manual/stdio.texi
+@@ -903,21 +903,21 @@ This function is a GNU extension.
+ @deftypefun int putc (int @var{c}, FILE *@var{stream})
+ @standards{ISO, stdio.h}
+ @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}}
+-This is just like @code{fputc}, except that most systems implement it as
++This is just like @code{fputc}, except that it may be implemented as
+ a macro, making it faster.  One consequence is that it may evaluate the
+ @var{stream} argument more than once, which is an exception to the
+-general rule for macros.  @code{putc} is usually the best function to
+-use for writing a single character.
++general rule for macros.  Therefore, @var{stream} should never be an
++expression with side-effects.
+ @end deftypefun
+ 
+ @deftypefun wint_t putwc (wchar_t @var{wc}, FILE *@var{stream})
+ @standards{ISO, wchar.h}
+ @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}}
+-This is just like @code{fputwc}, except that it can be implement as
++This is just like @code{fputwc}, except that it may be implemented as
+ a macro, making it faster.  One consequence is that it may evaluate the
+ @var{stream} argument more than once, which is an exception to the
+-general rule for macros.  @code{putwc} is usually the best function to
+-use for writing a single wide character.
++general rule for macros.  Therefore, @var{stream} should never be an
++expression with side-effects.
+ @end deftypefun
+ 
+ @deftypefun int putc_unlocked (int @var{c}, FILE *@var{stream})
diff --git a/SOURCES/glibc-upstream-2.39-94.patch b/SOURCES/glibc-upstream-2.39-94.patch
new file mode 100644
index 0000000000000000000000000000000000000000..22cf29d0fdd30901fd5148f74391b92905811c6a
--- /dev/null
+++ b/SOURCES/glibc-upstream-2.39-94.patch
@@ -0,0 +1,31 @@
+commit 4bdcc1963bc2b5ba5f8e319e402d9eb2cb6096c1
+Author: Lukas Bulwahn <lukas.bulwahn@redhat.com>
+Date:   Mon Jul 29 11:08:17 2024 +0200
+
+    manual: make setrlimit() description less ambiguous
+    
+    The existing description for setrlimit() has some ambiguity. It could be
+    understood to have the semantics of getrlimit(), i.e., the limits from the
+    process are stored in the provided rlp pointer.
+    
+    Make the description more explicit that rlp are the input values, and that
+    the limits of the process is changed with this function.
+    
+    Reviewed-by: Florian Weimer <fweimer@redhat.com>
+    (cherry picked from commit aedbf08891069fc029ed021e4dba933eb877b394)
+
+diff --git a/manual/resource.texi b/manual/resource.texi
+index 37462abc9e467690..743cc9439665b9d5 100644
+--- a/manual/resource.texi
++++ b/manual/resource.texi
+@@ -192,8 +192,8 @@ If the sources are compiled with @code{_FILE_OFFSET_BITS == 64} on a
+ @standards{BSD, sys/resource.h}
+ @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+ @c Direct syscall on most systems; lock-taking critical section on HURD.
+-Store the current and maximum limits for the resource @var{resource}
+-in @code{*@var{rlp}}.
++Change the current and maximum limits of the process for the resource
++@var{resource} to the values provided in @code{*@var{rlp}}.
+ 
+ The return value is @code{0} on success and @code{-1} on failure.  The
+ following @code{errno} error condition is possible:
diff --git a/SPECS/glibc.spec b/SPECS/glibc.spec
index 5a55f9107e71674d92ca67fb1b0a0411eeba1b93..d777452fab620019cb34b2340a43d6f7a0a27ba7 100644
--- a/SPECS/glibc.spec
+++ b/SPECS/glibc.spec
@@ -170,7 +170,7 @@ Version: %{glibcversion}
 # - It allows using the Release number without the %%dist tag in the dependency
 #   generator to make the generated requires interchangeable between Rawhide
 #   and ELN (.elnYY < .fcXX).
-%global baserelease 17
+%global baserelease 22
 Release: %{baserelease}%{?dist}
 
 # Licenses:
@@ -255,10 +255,10 @@ Source12: ChangeLog.old
 %endif
 %ifarch ppc64
 %global glibc_ldso /lib64/ld64.so.1
-%define glibc_rtld_early_cflags -mcpu=power8
 %endif
 %ifarch ppc64le
 %global glibc_ldso /lib64/ld64.so.2
+%define glibc_rtld_early_cflags -mcpu=power8
 %endif
 %ifarch riscv64
 %global glibc_ldso /lib/ld-linux-riscv64-lp64d.so.1
@@ -407,6 +407,30 @@ Patch96: glibc-upstream-2.39-72.patch
 # NEWS update: glibc-upstream-2.39-73.patch
 # NEWS update: glibc-upstream-2.39-74.patch
 Patch97: glibc-upstream-2.39-75.patch
+Patch98: glibc-rh2292195-1.patch
+Patch99: glibc-rh2292195-2.patch
+Patch100: glibc-rh2292195-3.patch
+Patch101: glibc-upstream-2.39-76.patch
+Patch102: glibc-upstream-2.39-77.patch
+Patch103: glibc-upstream-2.39-78.patch
+Patch104: glibc-upstream-2.39-79.patch
+Patch105: glibc-upstream-2.39-80.patch
+Patch106: glibc-upstream-2.39-81.patch
+Patch107: glibc-upstream-2.39-82.patch
+Patch108: glibc-upstream-2.39-83.patch
+Patch109: glibc-upstream-2.39-84.patch
+Patch110: glibc-upstream-2.39-85.patch
+Patch111: glibc-upstream-2.39-86.patch
+Patch112: glibc-upstream-2.39-87.patch
+Patch113: glibc-upstream-2.39-88.patch
+Patch114: glibc-upstream-2.39-89.patch
+Patch115: glibc-upstream-2.39-90.patch
+Patch116: glibc-upstream-2.39-91.patch
+Patch117: glibc-upstream-2.39-92.patch
+Patch118: glibc-upstream-2.39-93.patch
+Patch119: glibc-upstream-2.39-94.patch
+Patch120: RHEL-18039-1.patch
+Patch121: RHEL-18039-2.patch
 
 ##############################################################################
 # Continued list of core "glibc" package information:
@@ -437,6 +461,10 @@ Requires: basesystem
 # after nss_*.x86_64.  (See below for the other ordering.)
 Recommends: (nss_db(x86-32) if nss_db(x86-64))
 Recommends: (nss_hesiod(x86-32) if nss_hesiod(x86-64))
+# Deinstall the glibc32 package if present.  This helps tests that do
+# not run against the compose.
+Conflicts: glibc32 <= %{version}-%{release}
+Obsoletes: glibc32 <= %{version}-%{release}
 %endif
 
 # This is for building auxiliary programs like memusage
@@ -1156,6 +1184,7 @@ the glibc-devel package instead.
 %package utils
 Summary: Development utilities from GNU C library
 Requires: %{name} = %{version}-%{release}
+Requires: /usr/bin/perl
 
 %description utils
 The glibc-utils package contains memusage, a memory usage profiler,
@@ -2037,7 +2066,7 @@ grep \
 grep -e "gconv-modules-extra.conf" master.filelist > gconv.filelist
 
 # Put the essential gconv modules into the main package.
-GconvBaseModules="ANSI_X3.110 ISO8859-15 ISO8859-1 CP1252"
+GconvBaseModules="ISO8859-15 ISO8859-1 CP1252"
 GconvBaseModules="$GconvBaseModules UNICODE UTF-16 UTF-32 UTF-7"
 %ifarch s390 s390x
 GconvBaseModules="$GconvBaseModules ISO-8859-1_CP037_Z900 UTF8_UTF16_Z9"
@@ -2632,8 +2661,44 @@ update_gconv_modules_cache ()
 %endif
 
 %changelog
-* Mon Jun 24 2024 Troy Dawson <tdawson@redhat.com> - 2.39-17
-- Bump release for June 2024 mass rebuild
+* Wed Jul 31 2024 Florian Weimer <fweimer@redhat.com> - 2.39-22
+- Support clearing options in /etc/resolv.conf, RES_OPTIONS with a - prefix
+- Introduce the strict-error/RES_STRICTERR stub resolver option (RHEL-18039)
+
+* Wed Jul 31 2024 Arjun Shankar <arjun@redhat.com> - 2.39-21
+- Sync with upstream branch release/2.39/master,
+  commit 4bdcc1963bc2b5ba5f8e319e402d9eb2cb6096c1:
+- manual: make setrlimit() description less ambiguous
+- manual/stdio: Clarify putc and putwc
+- malloc: add multi-threaded tests for aligned_alloc/calloc/malloc
+- malloc: avoid global locks in tst-aligned_alloc-lib.c
+- resolv: Track single-request fallback via _res._flags (bug 31476)
+- resolv: Do not wait for non-existing second DNS response after error (bug 30081)
+- resolv: Allow short error responses to match any query (bug 31890)
+- elf: Fix localplt.awk for DT_RELR-enabled builds (BZ 31978)
+- Fix usage of _STACK_GROWS_DOWN and _STACK_GROWS_UP defines [BZ 31989]
+- Linux: Make __rseq_size useful for feature detection (bug 31965)
+- elf: Make dl-rseq-symbols Linux only
+- nptl: fix potential merge of __rseq_* relro symbols
+- s390x: Fix segfault in wcsncmp [BZ #31934]
+- stdlib: fix arc4random fallback to /dev/urandom (BZ 31612)
+- math: Provide missing math symbols on libc.a (BZ 31781)
+- math: Fix isnanf128 static build (BZ 31774)
+- math: Fix i386 and m68k exp10 on static build (BZ 31775)
+- math: Fix i386 and m68k fmod/fmodf on static build (BZ 31488)
+- posix: Fix pidfd_spawn/pidfd_spawnp leak if execve fails (BZ 31695)
+
+* Mon Jul 22 2024 Florian Weimer <fweimer@redhat.com> - 2.39-20
+- Support --without testsuite builds without perl installed (#2292195)
+
+* Fri Jul 19 2024 Florian Weimer <fweimer@redhat.com> - 2.39-19
+- Add Conflicts:/Obsoletes: for glibc32 to glibc.i686
+
+* Thu Jul 18 2024 Arjun Shankar <arjun@redhat.com> - 2.39-18
+- ppc64le: Build early startup code with -mcpu=power8
+
+* Tue Jul 02 2024 Patsy Griffin <patsy@redhat.com> - 2.39-17
+- Move ANSI_X3.110-1983 support from main package to glibc-gconv-extra.
 
 * Fri Jun 21 2024 Arjun Shankar <arjun@redhat.com> - 2.39-16
 - Sync with upstream branch release/2.39/master,