diff --git a/.glibc.checksum b/.glibc.checksum
index 42d241253fe8f17bd12ca358a7069a48733d2853..243d0059ed34457b3cd49dcee645b6cf9317896a 100644
--- a/.glibc.checksum
+++ b/.glibc.checksum
@@ -1 +1 @@
-47f3a67396f83ccee7645efe243af8eabcd8f749fc4901a295d8259be7375216
+609d4863fbcbcc09c71823c7b05065d719529c7500836bda2bc760b3f16d09f7
diff --git a/SOURCES/glibc-RHEL-46763-1.patch b/SOURCES/glibc-RHEL-46763-1.patch
new file mode 100644
index 0000000000000000000000000000000000000000..8440851f8acf89a28388e5513e0719fe7c167da1
--- /dev/null
+++ b/SOURCES/glibc-RHEL-46763-1.patch
@@ -0,0 +1,88 @@
+commit fe06fb313bddf7e4530056897d4a706606e49377
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Thu Aug 1 23:31:23 2024 +0200
+
+    elf: Clarify and invert second argument of _dl_allocate_tls_init
+    
+    Also remove an outdated comment: _dl_allocate_tls_init is
+    called as part of pthread_create.
+    
+    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+
+diff -Nrup a/elf/dl-tls.c b/elf/dl-tls.c
+--- a/elf/dl-tls.c	2024-08-21 13:11:01.422983765 -0400
++++ b/elf/dl-tls.c	2024-08-21 12:51:17.789904690 -0400
+@@ -558,9 +558,14 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_m
+ /* Allocate initial TLS.  RESULT should be a non-NULL pointer to storage
+    for the TLS space.  The DTV may be resized, and so this function may
+    call malloc to allocate that space.  The loader's GL(dl_load_tls_lock)
+-   is taken when manipulating global TLS-related data in the loader.  */
++   is taken when manipulating global TLS-related data in the loader.
++
++   If MAIN_THREAD, this is the first call during process
++   initialization.  In this case, TLS initialization for secondary
++   (audit) namespaces is skipped because that has already been handled
++   by dlopen.  */
+ void *
+-_dl_allocate_tls_init (void *result, bool init_tls)
++_dl_allocate_tls_init (void *result, bool main_thread)
+ {
+   if (result == NULL)
+     /* The memory allocation failed.  */
+@@ -639,7 +644,7 @@ _dl_allocate_tls_init (void *result, boo
+ 	     because it would already be set by the audit setup.  However,
+ 	     subsequent thread creation would need to follow the default
+ 	     behaviour.   */
+-	  if (map->l_ns != LM_ID_BASE && !init_tls)
++	  if (map->l_ns != LM_ID_BASE && main_thread)
+ 	    continue;
+ 	  memset (__mempcpy (dest, map->l_tls_initimage,
+ 			     map->l_tls_initimage_size), '\0',
+@@ -667,7 +672,7 @@ _dl_allocate_tls (void *mem)
+ {
+   return _dl_allocate_tls_init (mem == NULL
+ 				? _dl_allocate_tls_storage ()
+-				: allocate_dtv (mem), true);
++				: allocate_dtv (mem), false);
+ }
+ rtld_hidden_def (_dl_allocate_tls)
+ 
+diff -Nrup a/elf/rtld.c b/elf/rtld.c
+--- a/elf/rtld.c	2024-08-21 13:11:01.422983765 -0400
++++ b/elf/rtld.c	2024-08-21 12:57:33.134783030 -0400
+@@ -2485,7 +2485,7 @@ dl_main (const ElfW(Phdr) *phdr,
+      into the main thread's TLS area, which we allocated above.
+      Note: thread-local variables must only be accessed after completing
+      the next step.  */
+-  _dl_allocate_tls_init (tcbp, false);
++  _dl_allocate_tls_init (tcbp, true);
+ 
+   /* And finally install it for the main thread.  */
+   if (! tls_init_tp_called)
+diff -Nrup a/nptl/allocatestack.c b/nptl/allocatestack.c
+--- a/nptl/allocatestack.c	2024-08-21 13:11:00.640979593 -0400
++++ b/nptl/allocatestack.c	2024-08-21 12:51:17.789904690 -0400
+@@ -137,7 +137,7 @@ get_cached_stack (size_t *sizep, void **
+   memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t));
+ 
+   /* Re-initialize the TLS.  */
+-  _dl_allocate_tls_init (TLS_TPADJ (result), true);
++  _dl_allocate_tls_init (TLS_TPADJ (result), false);
+ 
+   return result;
+ }
+diff -Nrup a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
+--- a/sysdeps/generic/ldsodefs.h	2024-08-21 13:11:01.423983770 -0400
++++ b/sysdeps/generic/ldsodefs.h	2024-08-21 13:30:39.072207595 -0400
+@@ -1258,10 +1258,8 @@ extern void _dl_get_tls_static_info (siz
+ 
+ extern void _dl_allocate_static_tls (struct link_map *map) attribute_hidden;
+ 
+-/* These are internal entry points to the two halves of _dl_allocate_tls,
+-   only used within rtld.c itself at startup time.  */
+ extern void *_dl_allocate_tls_storage (void) attribute_hidden;
+-extern void *_dl_allocate_tls_init (void *, bool);
++extern void *_dl_allocate_tls_init (void *result, bool main_thread);
+ rtld_hidden_proto (_dl_allocate_tls_init)
+ 
+ /* Deallocate memory allocated with _dl_allocate_tls.  */
diff --git a/SOURCES/glibc-RHEL-46763-2.patch b/SOURCES/glibc-RHEL-46763-2.patch
new file mode 100644
index 0000000000000000000000000000000000000000..18b412458d57c06b7c7182d08d25502aa2517204
--- /dev/null
+++ b/SOURCES/glibc-RHEL-46763-2.patch
@@ -0,0 +1,524 @@
+commit 5097cd344fd243fb8deb6dec96e8073753f962f9
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Thu Aug 1 23:31:30 2024 +0200
+
+    elf: Avoid re-initializing already allocated TLS in dlopen (bug 31717)
+    
+    The old code used l_init_called as an indicator for whether TLS
+    initialization was complete.  However, it is possible that
+    TLS for an object is initialized, written to, and then dlopen
+    for this object is called again, and l_init_called is not true at
+    this point.  Previously, this resulted in TLS being initialized
+    twice, discarding any interim writes (technically introducing a
+    use-after-free bug even).
+    
+    This commit introduces an explicit per-object flag, l_tls_in_slotinfo.
+    It indicates whether _dl_add_to_slotinfo has been called for this
+    object.  This flag is used to avoid double-initialization of TLS.
+    In update_tls_slotinfo, the first_static_tls micro-optimization
+    is removed because preserving the initalization flag for subsequent
+    use by the second loop for static TLS is a bit complicated, and
+    another per-object flag does not seem to be worth it.  Furthermore,
+    the l_init_called flag is dropped from the second loop (for static
+    TLS initialization) because l_need_tls_init on its own prevents
+    double-initialization.
+    
+    The remaining l_init_called usage in resize_scopes and update_scopes
+    is just an optimization due to the use of scope_has_map, so it is
+    not changed in this commit.
+    
+    The isupper check ensures that libc.so.6 is TLS is not reverted.
+    Such a revert happens if l_need_tls_init is not cleared in
+    _dl_allocate_tls_init for the main_thread case, now that
+    l_init_called is not checked anymore in update_tls_slotinfo
+    in elf/dl-open.c.
+    
+    Reported-by: Jonathon Anderson <janderson@rice.edu>
+    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+
+    Conflicts:
+	elf/Makefile - usual tests list differences
+
+diff -Nrup a/elf/Makefile b/elf/Makefile
+--- a/elf/Makefile	2024-08-21 14:24:25.311070834 -0400
++++ b/elf/Makefile	2024-08-21 14:16:19.905503937 -0400
+@@ -399,6 +399,10 @@ tests += \
+   tst-dlmopen-dlerror \
+   tst-dlmopen-gethostbyname \
+   tst-dlmopen-twice \
++  tst-dlopen-tlsreinit1 \
++  tst-dlopen-tlsreinit2 \
++  tst-dlopen-tlsreinit3 \
++  tst-dlopen-tlsreinit4 \
+   tst-dlopenfail \
+   tst-dlopenfail-2 \
+   tst-dlopenrpath \
+@@ -753,6 +757,9 @@ modules-names = \
+   tst-dlmopen-gethostbyname-mod \
+   tst-dlmopen-twice-mod1 \
+   tst-dlmopen-twice-mod2 \
++  tst-dlopen-tlsreinitmod1 \
++  tst-dlopen-tlsreinitmod2 \
++  tst-dlopen-tlsreinitmod3 \
+   tst-dlopenfaillinkmod \
+   tst-dlopenfailmod1 \
+   tst-dlopenfailmod2 \
+@@ -2751,3 +2758,26 @@ $(objpfx)tst-recursive-tls.out: \
+     0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
+ $(objpfx)tst-recursive-tlsmod%.os: tst-recursive-tlsmodN.c
+ 	$(compile-command.c) -DVAR=thread_$* -DFUNC=get_threadvar_$*
++
++# Order matters here.  The test needs the constructor for
++# tst-dlopen-tlsreinitmod2.so to be called first.
++LDFLAGS-tst-dlopen-tlsreinitmod1.so = -Wl,--no-as-needed
++$(objpfx)tst-dlopen-tlsreinitmod1.so: \
++  $(objpfx)tst-dlopen-tlsreinitmod3.so $(objpfx)tst-dlopen-tlsreinitmod2.so
++LDFLAGS-tst-dlopen-tlsreinit2 = -Wl,--no-as-needed
++$(objpfx)tst-dlopen-tlsreinit2: \
++  $(objpfx)tst-dlopen-tlsreinitmod3.so $(objpfx)tst-dlopen-tlsreinitmod2.so
++LDFLAGS-tst-dlopen-tlsreinit4 = -Wl,--no-as-needed
++$(objpfx)tst-dlopen-tlsreinit4: \
++  $(objpfx)tst-dlopen-tlsreinitmod3.so $(objpfx)tst-dlopen-tlsreinitmod2.so
++# tst-dlopen-tlsreinitmod2.so is underlinked and refers to
++# tst-dlopen-tlsreinitmod3.so.  The dependency is provided via
++# $(objpfx)tst-dlopen-tlsreinitmod1.so.
++tst-dlopen-tlsreinitmod2.so-no-z-defs = yes
++$(objpfx)tst-dlopen-tlsreinit.out: $(objpfx)tst-dlopen-tlsreinitmod1.so \
++  $(objpfx)tst-dlopen-tlsreinitmod2.so $(objpfx)tst-dlopen-tlsreinitmod3.so
++# Reuse an audit module which provides ample debug logging.
++$(objpfx)tst-dlopen-tlsreinit3.out: $(objpfx)tst-auditmod1.so
++tst-dlopen-tlsreinit3-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
++$(objpfx)tst-dlopen-tlsreinit4.out: $(objpfx)tst-auditmod1.so
++tst-dlopen-tlsreinit4-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
+diff -Nrup a/elf/dl-open.c b/elf/dl-open.c
+--- a/elf/dl-open.c	2024-08-21 14:24:25.273070633 -0400
++++ b/elf/dl-open.c	2024-08-21 14:04:52.834912875 -0400
+@@ -362,17 +362,8 @@ resize_tls_slotinfo (struct link_map *ne
+ {
+   bool any_tls = false;
+   for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
+-    {
+-      struct link_map *imap = new->l_searchlist.r_list[i];
+-
+-      /* Only add TLS memory if this object is loaded now and
+-	 therefore is not yet initialized.  */
+-      if (! imap->l_init_called && imap->l_tls_blocksize > 0)
+-	{
+-	  _dl_add_to_slotinfo (imap, false);
+-	  any_tls = true;
+-	}
+-    }
++    if (_dl_add_to_slotinfo (new->l_searchlist.r_list[i], false))
++      any_tls = true;
+   return any_tls;
+ }
+ 
+@@ -382,22 +373,8 @@ resize_tls_slotinfo (struct link_map *ne
+ static void
+ update_tls_slotinfo (struct link_map *new)
+ {
+-  unsigned int first_static_tls = new->l_searchlist.r_nlist;
+   for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
+-    {
+-      struct link_map *imap = new->l_searchlist.r_list[i];
+-
+-      /* Only add TLS memory if this object is loaded now and
+-	 therefore is not yet initialized.  */
+-      if (! imap->l_init_called && imap->l_tls_blocksize > 0)
+-	{
+-	  _dl_add_to_slotinfo (imap, true);
+-
+-	  if (imap->l_need_tls_init
+-	      && first_static_tls == new->l_searchlist.r_nlist)
+-	    first_static_tls = i;
+-	}
+-    }
++    _dl_add_to_slotinfo (new->l_searchlist.r_list[i], true);
+ 
+   size_t newgen = GL(dl_tls_generation) + 1;
+   if (__glibc_unlikely (newgen == 0))
+@@ -409,13 +386,11 @@ TLS generation counter wrapped!  Please
+   /* We need a second pass for static tls data, because
+      _dl_update_slotinfo must not be run while calls to
+      _dl_add_to_slotinfo are still pending.  */
+-  for (unsigned int i = first_static_tls; i < new->l_searchlist.r_nlist; ++i)
++  for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
+     {
+       struct link_map *imap = new->l_searchlist.r_list[i];
+ 
+-      if (imap->l_need_tls_init
+-	  && ! imap->l_init_called
+-	  && imap->l_tls_blocksize > 0)
++      if (imap->l_need_tls_init && imap->l_tls_blocksize > 0)
+ 	{
+ 	  /* For static TLS we have to allocate the memory here and
+ 	     now, but we can delay updating the DTV.  */
+diff -Nrup a/elf/dl-tls.c b/elf/dl-tls.c
+--- a/elf/dl-tls.c	2024-08-21 14:24:25.315070855 -0400
++++ b/elf/dl-tls.c	2024-08-21 14:20:34.569850644 -0400
+@@ -638,17 +638,21 @@ _dl_allocate_tls_init (void *result, boo
+ 	     some platforms use in static programs requires it.  */
+ 	  dtv[map->l_tls_modid].pointer.val = dest;
+ 
+-	  /* Copy the initialization image and clear the BSS part.  For
+-	     audit modules or dependencies with initial-exec TLS, we can not
+-	     set the initial TLS image on default loader initialization
+-	     because it would already be set by the audit setup.  However,
+-	     subsequent thread creation would need to follow the default
+-	     behaviour.   */
++	  /* Copy the initialization image and clear the BSS part.
++	     For audit modules or dependencies with initial-exec TLS,
++	     we can not set the initial TLS image on default loader
++	     initialization because it would already be set by the
++	     audit setup, which uses the dlopen code and already
++	     clears l_need_tls_init.  Calls with !main_thread from
++	     pthread_create need to initialze TLS for the current
++	     thread regardless of namespace.  */
+ 	  if (map->l_ns != LM_ID_BASE && main_thread)
+ 	    continue;
+ 	  memset (__mempcpy (dest, map->l_tls_initimage,
+ 			     map->l_tls_initimage_size), '\0',
+ 		  map->l_tls_blocksize - map->l_tls_initimage_size);
++	  if (main_thread)
++	    map->l_need_tls_init = 0;
+ 	}
+ 
+       total += cnt;
+@@ -1105,9 +1109,32 @@ _dl_tls_initial_modid_limit_setup (void)
+ }
+ 
+ 
+-void
++/* Add module to slot information data.  If DO_ADD is false, only the
++   required memory is allocated.  Must be called with
++   GL (dl_load_tls_lock) acquired.  If the function has already been
++   called for the link map L with !DO_ADD, then this function will not
++   raise an exception, otherwise it is possible that it encounters a
++   memory allocation failure.
++
++   Return false if L has already been added to the slotinfo data, or
++   if L has no TLS data.  If the returned value is true, L has been
++   added with this call (DO_ADD), or has been added in a previous call
++   (!DO_ADD).
++
++   The expected usage is as follows: Call _dl_add_to_slotinfo for
++   several link maps with DO_ADD set to false, and record if any calls
++   result in a true result.  If there was a true result, call
++   _dl_add_to_slotinfo again, this time with DO_ADD set to true.  (For
++   simplicity, it's possible to call the function for link maps where
++   the previous result was false.)  The return value from the second
++   round of calls can be ignored.  If there was true result initially,
++   call _dl_update_slotinfo to update the TLS generation counter.  */
++bool
+ _dl_add_to_slotinfo (struct link_map *l, bool do_add)
+ {
++  if (l->l_tls_blocksize == 0 || l->l_tls_in_slotinfo)
++    return false;
++
+   /* Now that we know the object is loaded successfully add
+      modules containing TLS data to the dtv info table.  We
+      might have to increase its size.  */
+@@ -1163,7 +1190,10 @@ cannot create TLS data structures"));
+       atomic_store_relaxed (&listp->slotinfo[idx].map, l);
+       atomic_store_relaxed (&listp->slotinfo[idx].gen,
+ 			    GL(dl_tls_generation) + 1);
++      l->l_tls_in_slotinfo = true;
+     }
++
++  return true;
+ }
+ 
+ #if THREAD_GSCOPE_IN_TCB
+diff -Nrup a/elf/tst-dlopen-tlsreinit1.c b/elf/tst-dlopen-tlsreinit1.c
+--- a/elf/tst-dlopen-tlsreinit1.c	1969-12-31 19:00:00.000000000 -0500
++++ b/elf/tst-dlopen-tlsreinit1.c	2024-08-21 14:04:52.834912875 -0400
+@@ -0,0 +1,40 @@
++/* Test that dlopen preserves already accessed TLS (bug 31717).
++   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 <stdbool.h>
++#include <support/check.h>
++#include <support/xdlfcn.h>
++#include <ctype.h>
++
++static int
++do_test (void)
++{
++  void *handle = xdlopen ("tst-dlopen-tlsreinitmod1.so", RTLD_NOW);
++
++  bool *tlsreinitmod3_tested = xdlsym (handle, "tlsreinitmod3_tested");
++  TEST_VERIFY (*tlsreinitmod3_tested);
++
++  xdlclose (handle);
++
++  /* This crashes if the libc.so.6 TLS image has been reverted.  */
++  TEST_VERIFY (!isupper ('@'));
++
++  return 0;
++}
++
++#include <support/test-driver.c>
+diff -Nrup a/elf/tst-dlopen-tlsreinit2.c b/elf/tst-dlopen-tlsreinit2.c
+--- a/elf/tst-dlopen-tlsreinit2.c	1969-12-31 19:00:00.000000000 -0500
++++ b/elf/tst-dlopen-tlsreinit2.c	2024-08-21 14:04:52.834912875 -0400
+@@ -0,0 +1,39 @@
++/* Test that dlopen preserves already accessed TLS (bug 31717).
++   Variant with initially-linked modules.
++   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 <ctype.h>
++#include <stdbool.h>
++#include <support/check.h>
++#include <support/xdlfcn.h>
++
++
++static int
++do_test (void)
++{
++  /* Defined in tst-dlopen-tlsreinitmod3.so.  */
++  extern bool tlsreinitmod3_tested;
++  TEST_VERIFY (tlsreinitmod3_tested);
++
++  /* This crashes if the libc.so.6 TLS image has been reverted.  */
++  TEST_VERIFY (!isupper ('@'));
++
++  return 0;
++}
++
++#include <support/test-driver.c>
+diff -Nrup a/elf/tst-dlopen-tlsreinit3.c b/elf/tst-dlopen-tlsreinit3.c
+--- a/elf/tst-dlopen-tlsreinit3.c	1969-12-31 19:00:00.000000000 -0500
++++ b/elf/tst-dlopen-tlsreinit3.c	2024-08-21 14:04:52.834912875 -0400
+@@ -0,0 +1,2 @@
++/* Same code, but run with LD_AUDIT=tst-auditmod1.so.  */
++#include "tst-dlopen-tlsreinit1.c"
+diff -Nrup a/elf/tst-dlopen-tlsreinit4.c b/elf/tst-dlopen-tlsreinit4.c
+--- a/elf/tst-dlopen-tlsreinit4.c	1969-12-31 19:00:00.000000000 -0500
++++ b/elf/tst-dlopen-tlsreinit4.c	2024-08-21 14:04:52.834912875 -0400
+@@ -0,0 +1,2 @@
++/* Same code, but run with LD_AUDIT=tst-auditmod1.so.  */
++#include "tst-dlopen-tlsreinit2.c"
+diff -Nrup a/elf/tst-dlopen-tlsreinitmod1.c b/elf/tst-dlopen-tlsreinitmod1.c
+--- a/elf/tst-dlopen-tlsreinitmod1.c	1969-12-31 19:00:00.000000000 -0500
++++ b/elf/tst-dlopen-tlsreinitmod1.c	2024-08-21 14:04:52.834912875 -0400
+@@ -0,0 +1,20 @@
++/* Test that dlopen preserves already accessed TLS (bug 31717), module 1.
++   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/>.  */
++
++/* This module triggers loading of tst-dlopen-tlsreinitmod2.so and
++   tst-dlopen-tlsreinitmod3.so.  */
+diff -Nrup a/elf/tst-dlopen-tlsreinitmod2.c b/elf/tst-dlopen-tlsreinitmod2.c
+--- a/elf/tst-dlopen-tlsreinitmod2.c	1969-12-31 19:00:00.000000000 -0500
++++ b/elf/tst-dlopen-tlsreinitmod2.c	2024-08-21 14:04:52.835912880 -0400
+@@ -0,0 +1,30 @@
++/* Test that dlopen preserves already accessed TLS (bug 31717), module 2.
++   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 <stdio.h>
++
++/* Defined in tst-dlopen-tlsreinitmod3.so.  This an underlinked symbol
++   dependency.  */
++extern void call_tlsreinitmod3 (void);
++
++static void __attribute__ ((constructor))
++tlsreinitmod2_init (void)
++{
++  puts ("info: constructor of tst-dlopen-tlsreinitmod2.so invoked");
++  call_tlsreinitmod3 ();
++}
+diff -Nrup a/elf/tst-dlopen-tlsreinitmod3.c b/elf/tst-dlopen-tlsreinitmod3.c
+--- a/elf/tst-dlopen-tlsreinitmod3.c	1969-12-31 19:00:00.000000000 -0500
++++ b/elf/tst-dlopen-tlsreinitmod3.c	2024-08-21 14:04:52.835912880 -0400
+@@ -0,0 +1,102 @@
++/* Test that dlopen preserves already accessed TLS (bug 31717), module 3.
++   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 <dlfcn.h>
++#include <stdbool.h>
++#include <stdio.h>
++#include <unistd.h>
++
++/* Used to verify from the main program that the test ran.  */
++bool tlsreinitmod3_tested;
++
++/* This TLS variable must not revert back to the initial state after
++   dlopen.  */
++static __thread int tlsreinitmod3_state = 1;
++
++/* Set from the ELF constructor during dlopen.  */
++static bool tlsreinitmod3_constructed;
++
++/* Second half of test, behind a compiler barrier.  The compiler
++   barrier is necessary to prevent carrying over TLS address
++   information from call_tlsreinitmod3 to call_tlsreinitmod3_tail.  */
++void call_tlsreinitmod3_tail (void *self) __attribute__ ((weak));
++
++/* Called from tst-dlopen-tlsreinitmod2.so.  */
++void
++call_tlsreinitmod3 (void)
++{
++  printf ("info: call_tlsreinitmod3 invoked (state=%d)\n",
++          tlsreinitmod3_state);
++
++  if (tlsreinitmod3_constructed)
++    {
++      puts ("error: call_tlsreinitmod3 called after ELF constructor");
++      fflush (stdout);
++      /* Cannot rely on test harness due to dynamic linking.  */
++      _exit (1);
++    }
++
++  tlsreinitmod3_state = 2;
++
++  /* Self-dlopen.  This will run the ELF constructor.   */
++  void *self = dlopen ("tst-dlopen-tlsreinitmod3.so", RTLD_NOW);
++  if (self == NULL)
++    {
++      printf ("error: dlopen: %s\n", dlerror ());
++      fflush (stdout);
++      /* Cannot rely on test harness due to dynamic linking.  */
++      _exit (1);
++    }
++
++  call_tlsreinitmod3_tail (self);
++}
++
++void
++call_tlsreinitmod3_tail (void *self)
++{
++  printf ("info: dlopen returned in tlsreinitmod3 (state=%d)\n",
++          tlsreinitmod3_state);
++
++  if (!tlsreinitmod3_constructed)
++    {
++      puts ("error: dlopen did not call tlsreinitmod3 ELF constructor");
++      fflush (stdout);
++      /* Cannot rely on test harness due to dynamic linking.  */
++      _exit (1);
++    }
++
++  if (tlsreinitmod3_state != 2)
++    {
++      puts ("error: TLS state reverted in tlsreinitmod3");
++      fflush (stdout);
++      /* Cannot rely on test harness due to dynamic linking.  */
++      _exit (1);
++    }
++
++  dlclose (self);
++
++  /* Signal test completion to the main program.  */
++  tlsreinitmod3_tested = true;
++}
++
++static void __attribute__ ((constructor))
++tlsreinitmod3_init (void)
++{
++  puts ("info: constructor of tst-dlopen-tlsreinitmod3.so invoked");
++  tlsreinitmod3_constructed = true;
++}
+diff -Nrup a/include/link.h b/include/link.h
+--- a/include/link.h	2024-08-21 14:24:24.556066841 -0400
++++ b/include/link.h	2024-08-21 14:23:54.674908823 -0400
+@@ -211,6 +211,8 @@ struct link_map
+ 				       freed, ie. not allocated with
+ 				       the dummy malloc in ld.so.  */
+     unsigned int l_ld_readonly:1; /* Nonzero if dynamic section is readonly.  */
++    unsigned int l_tls_in_slotinfo:1; /* TLS slotinfo updated in dlopen.  */
++
+ 
+     /* NODELETE status of the map.  Only valid for maps of type
+        lt_loaded.  Lazy binding sets l_nodelete_active directly,
+diff -Nrup a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
+--- a/sysdeps/generic/ldsodefs.h	2024-08-21 14:24:25.317070865 -0400
++++ b/sysdeps/generic/ldsodefs.h	2024-08-21 14:04:52.835912880 -0400
+@@ -1291,13 +1291,7 @@ extern void *_dl_open (const char *name,
+ extern int _dl_scope_free (void *) attribute_hidden;
+ 
+ 
+-/* Add module to slot information data.  If DO_ADD is false, only the
+-   required memory is allocated.  Must be called with GL
+-   (dl_load_tls_lock) acquired.  If the function has already been called
+-   for the link map L with !do_add, then this function will not raise
+-   an exception, otherwise it is possible that it encounters a memory
+-   allocation failure.  */
+-extern void _dl_add_to_slotinfo (struct link_map *l, bool do_add)
++extern bool _dl_add_to_slotinfo (struct link_map *l, bool do_add)
+   attribute_hidden;
+ 
+ /* Update slot information data for at least the generation of the
diff --git a/SOURCES/glibc-RHEL-46763-3.patch b/SOURCES/glibc-RHEL-46763-3.patch
new file mode 100644
index 0000000000000000000000000000000000000000..a2b3e7699e1d831d5db812fc03561f55542bf34d
--- /dev/null
+++ b/SOURCES/glibc-RHEL-46763-3.patch
@@ -0,0 +1,16 @@
+Author: Patsy Griffin <patsy@redhat.com>
+  
+    Fix a typo in naming tst-dlopen-tlsreinit1.out
+
+diff -Nrup a/elf/Makefile b/elf/Makefile
+--- a/elf/Makefile	2024-08-16 13:27:00.700921146 -0400
++++ b/elf/Makefile	2024-08-16 13:29:12.951628406 -0400
+@@ -2802,7 +2802,7 @@ $(objpfx)tst-dlopen-tlsreinit4: \
+ # tst-dlopen-tlsreinitmod3.so.  The dependency is provided via
+ # $(objpfx)tst-dlopen-tlsreinitmod1.so.
+ tst-dlopen-tlsreinitmod2.so-no-z-defs = yes
+-$(objpfx)tst-dlopen-tlsreinit.out: $(objpfx)tst-dlopen-tlsreinitmod1.so \
++$(objpfx)tst-dlopen-tlsreinit1.out: $(objpfx)tst-dlopen-tlsreinitmod1.so \
+   $(objpfx)tst-dlopen-tlsreinitmod2.so $(objpfx)tst-dlopen-tlsreinitmod3.so
+ # Reuse an audit module which provides ample debug logging.
+ $(objpfx)tst-dlopen-tlsreinit3.out: $(objpfx)tst-auditmod1.so
diff --git a/SPECS/glibc.spec b/SPECS/glibc.spec
index 599d2824a61570aa9456492cdb3368c70f23d1f7..f1d2ec3181fba003f8abe2dd1d74995104a2c049 100644
--- a/SPECS/glibc.spec
+++ b/SPECS/glibc.spec
@@ -155,7 +155,7 @@ end \
 Summary: The GNU libc libraries
 Name: glibc
 Version: %{glibcversion}
-Release: 100%{?dist}.3
+Release: 100%{?dist}.4
 
 # In general, GPLv2+ is used by programs, LGPLv2+ is used for
 # libraries.
@@ -815,6 +815,9 @@ Patch578: glibc-RHEL-34318-3.patch
 Patch579: glibc-RHEL-34318-4.patch
 Patch580: glibc-RHEL-39993-1.patch
 Patch581: glibc-RHEL-39993-2.patch
+Patch582: glibc-RHEL-46763-1.patch
+Patch583: glibc-RHEL-46763-2.patch
+Patch584: glibc-RHEL-46763-3.patch
 
 ##############################################################################
 # Continued list of core "glibc" package information:
@@ -2973,6 +2976,10 @@ update_gconv_modules_cache ()
 %endif
 
 %changelog
+* Tue Aug 27 2024 Patsy Griffin <patsy@redhat.com> - 2.34-100.4
+- elf: Clarify and invert second argument of _dl_allocate_tls_init
+- elf: Avoid re-initializing already allocated TLS in dlopen (RHEL-46763)
+
 * Fri Jul 12 2024 Patsy Griffin <patsy@redhat.com> - 2.34-100.3
 - elf: Avoid some free (NULL) calls in _dl_update_slotinfo
 - elf: Support recursive use of dynamic TLS in interposed malloc (RHEL-39993)