diff --git a/SOURCES/glibc-RHEL-10481.patch b/SOURCES/glibc-RHEL-10481.patch
new file mode 100644
index 0000000..825f13c
--- /dev/null
+++ b/SOURCES/glibc-RHEL-10481.patch
@@ -0,0 +1,112 @@
+commit 849274d48fc59bfa6db3c713c8ced8026b20f3b7
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Thu Nov 16 19:55:35 2023 +0100
+
+    elf: Fix force_first handling in dlclose (bug 30981)
+    
+    The force_first parameter was ineffective because the dlclose'd
+    object was not necessarily the first in the maps array.  Also
+    enable force_first handling unconditionally, regardless of namespace.
+    The initial object in a namespace should be destructed first, too.
+    
+    The _dl_sort_maps_dfs function had early returns for relocation
+    dependency processing which broke force_first handling, too, and
+    this is fixed in this change as well.
+    
+    Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
+
+diff --git a/elf/dl-close.c b/elf/dl-close.c
+index 66524b6708c59f29..8107c2d5f6ad2bc6 100644
+--- a/elf/dl-close.c
++++ b/elf/dl-close.c
+@@ -182,6 +182,16 @@ _dl_close_worker (struct link_map *map, bool force)
+     }
+   assert (idx == nloaded);
+ 
++  /* Put the dlclose'd map first, so that its destructor runs first.
++     The map variable is NULL after a retry.  */
++  if (map != NULL)
++    {
++      maps[map->l_idx] = maps[0];
++      maps[map->l_idx]->l_idx = map->l_idx;
++      maps[0] = map;
++      maps[0]->l_idx = 0;
++    }
++
+   /* Keep track of the lowest index link map we have covered already.  */
+   int done_index = -1;
+   while (++done_index < nloaded)
+@@ -255,9 +265,10 @@ _dl_close_worker (struct link_map *map, bool force)
+ 	  }
+     }
+ 
+-  /* Sort the entries.  We can skip looking for the binary itself which is
+-     at the front of the search list for the main namespace.  */
+-  _dl_sort_maps (maps, nloaded, (nsid == LM_ID_BASE), true);
++  /* Sort the entries.  Unless retrying, the maps[0] object (the
++     original argument to dlclose) needs to remain first, so that its
++     destructor runs first.  */
++  _dl_sort_maps (maps, nloaded, /* force_first */ map != NULL, true);
+ 
+   /* Call all termination functions at once.  */
+   bool unload_any = false;
+@@ -768,7 +779,11 @@ _dl_close_worker (struct link_map *map, bool force)
+   /* Recheck if we need to retry, release the lock.  */
+  out:
+   if (dl_close_state == rerun)
+-    goto retry;
++    {
++      /* The map may have been deallocated.  */
++      map = NULL;
++      goto retry;
++    }
+ 
+   dl_close_state = not_pending;
+ }
+diff --git a/elf/dl-sort-maps.c b/elf/dl-sort-maps.c
+index aeb79b40b45054c0..c17ac325eca658ef 100644
+--- a/elf/dl-sort-maps.c
++++ b/elf/dl-sort-maps.c
+@@ -260,13 +260,12 @@ _dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps,
+ 	     The below memcpy is not needed in the do_reldeps case here,
+ 	     since we wrote back to maps[] during DFS traversal.  */
+ 	  if (maps_head == maps)
+-	    return;
++	    break;
+ 	}
+       assert (maps_head == maps);
+-      return;
+     }
+-
+-  memcpy (maps, rpo, sizeof (struct link_map *) * nmaps);
++  else
++    memcpy (maps, rpo, sizeof (struct link_map *) * nmaps);
+ 
+   /* Skipping the first object at maps[0] is not valid in general,
+      since traversing along object dependency-links may "find" that
+diff --git a/elf/dso-sort-tests-1.def b/elf/dso-sort-tests-1.def
+index 4bf9052db16fb352..cf6453e9eb85ac65 100644
+--- a/elf/dso-sort-tests-1.def
++++ b/elf/dso-sort-tests-1.def
+@@ -56,14 +56,16 @@ output: b>a>{}<a<b
+ # relocation(dynamic) dependencies. While this is technically unspecified, the
+ # presumed reasonable practical behavior is for the destructor order to respect
+ # the static DT_NEEDED links (here this means the a->b->c->d order).
+-# The older dynamic_sort=1 algorithm does not achieve this, while the DFS-based
+-# dynamic_sort=2 algorithm does, although it is still arguable whether going
+-# beyond spec to do this is the right thing to do.
++# The older dynamic_sort=1 algorithm originally did not achieve this,
++# but this was a bug in the way _dl_sort_maps was called from _dl_close_worker,
++# effectively disabling proper force_first handling.
++# The new dynamic_sort=2 algorithm shows the effect of the simpler force_first
++# handling: the a object is simply moved to the front.
+ # The below expected outputs are what the two algorithms currently produce
+ # respectively, for regression testing purposes.
+ tst-bz15311: {+a;+e;+f;+g;+d;%d;-d;-g;-f;-e;-a};a->b->c->d;d=>[ba];c=>a;b=>e=>a;c=>f=>b;d=>g=>c
+-output(glibc.rtld.dynamic_sort=1): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<a<c<d<g<f<b<e];}
+-output(glibc.rtld.dynamic_sort=2): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<g<f<a<b<c<d<e];}
++output(glibc.rtld.dynamic_sort=1): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<a<b<c<d<g<f<e];}
++output(glibc.rtld.dynamic_sort=2): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<a<g<f<b<c<d<e];}
+ 
+ # Test that even in the presence of dependency loops involving dlopen'ed
+ # object, that object is initialized last (and not unloaded prematurely).
diff --git a/SOURCES/glibc-RHEL-3639.patch b/SOURCES/glibc-RHEL-3639.patch
new file mode 100644
index 0000000..e51ab13
--- /dev/null
+++ b/SOURCES/glibc-RHEL-3639.patch
@@ -0,0 +1,235 @@
+commit d0f07f7df8d9758c838674b70144ac73bcbd1634
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Tue May 30 13:25:50 2023 +0200
+
+    elf: Make more functions available for binding during dlclose (bug 30425)
+    
+    Previously, after destructors for a DSO have been invoked, ld.so refused
+    to bind against that DSO in all cases.  Relax this restriction somewhat
+    if the referencing object is itself a DSO that is being unloaded.  This
+    assumes that the symbol reference is not going to be stored anywhere.
+    
+    The situation in the test case can arise fairly easily with C++ and
+    objects that are built with different optimization levels and therefore
+    define different functions with vague linkage.
+    
+    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+
+Conflicts:
+	elf/Makefile
+	  (usual test differences, link test with -ldl)
+
+diff --git a/elf/Makefile b/elf/Makefile
+index 634c3113227d64a6..42dc878209b11d29 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -362,6 +362,7 @@ tests += \
+   tst-big-note \
+   tst-debug1 \
+   tst-deep1 \
++  tst-dlclose-lazy \
+   tst-dlmodcount \
+   tst-dlmopen1 \
+   tst-dlmopen3 \
+@@ -709,6 +710,8 @@ modules-names = \
+   tst-deep1mod2 \
+   tst-deep1mod3 \
+   tst-dlmopen1mod \
++  tst-dlclose-lazy-mod1 \
++  tst-dlclose-lazy-mod2 \
+   tst-dlmopen-dlerror-mod \
+   tst-dlmopen-gethostbyname-mod \
+   tst-dlmopen-twice-mod1 \
+@@ -2697,3 +2700,10 @@ $(objpfx)tst-dlmopen-twice: $(libdl)
+ $(objpfx)tst-dlmopen-twice.out: \
+   $(objpfx)tst-dlmopen-twice-mod1.so \
+   $(objpfx)tst-dlmopen-twice-mod2.so
++
++LDFLAGS-tst-dlclose-lazy-mod1.so = -Wl,-z,lazy,--no-as-needed
++$(objpfx)tst-dlclose-lazy-mod1.so: $(objpfx)tst-dlclose-lazy-mod2.so
++$(objpfx)tst-dlclose-lazy: $(libdl)
++$(objpfx)tst-dlclose-lazy.out: \
++  $(objpfx)tst-dlclose-lazy-mod1.so $(objpfx)tst-dlclose-lazy-mod2.so
++
+diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
+index 47acd134600b44b5..9e8f14b8483f5eba 100644
+--- a/elf/dl-lookup.c
++++ b/elf/dl-lookup.c
+@@ -380,8 +380,25 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
+       if ((type_class & ELF_RTYPE_CLASS_COPY) && map->l_type == lt_executable)
+ 	continue;
+ 
+-      /* Do not look into objects which are going to be removed.  */
+-      if (map->l_removed)
++      /* Do not look into objects which are going to be removed,
++	 except when the referencing object itself is being removed.
++
++	 The second part covers the situation when an object lazily
++	 binds to another object while running its destructor, but the
++	 destructor of the other object has already run, so that
++	 dlclose has set l_removed.  It may not always be obvious how
++	 to avoid such a scenario to programmers creating DSOs,
++	 particularly if C++ vague linkage is involved and triggers
++	 symbol interposition.
++
++	 Accepting these to-be-removed objects makes the lazy and
++	 BIND_NOW cases more similar.  (With BIND_NOW, the symbol is
++	 resolved early, before the destructor call, so the issue does
++	 not arise.).  Behavior matches the constructor scenario: the
++	 implementation allows binding to symbols of objects whose
++	 constructors have not run.  In fact, not doing this would be
++	 mostly incompatible with symbol interposition.  */
++      if (map->l_removed && !(undef_map != NULL && undef_map->l_removed))
+ 	continue;
+ 
+       /* Print some debugging info if wanted.  */
+diff --git a/elf/tst-dlclose-lazy-mod1.c b/elf/tst-dlclose-lazy-mod1.c
+new file mode 100644
+index 0000000000000000..8439dc1925cc8b41
+--- /dev/null
++++ b/elf/tst-dlclose-lazy-mod1.c
+@@ -0,0 +1,36 @@
++/* Lazy binding during dlclose.  Directly loaded module.
++   Copyright (C) 2023 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 function is called from exported_function below.  It is only
++   defined in this module.  The weak attribute mimics how G++
++   implements vague linkage for C++.  */
++void __attribute__ ((weak))
++lazily_bound_exported_function (void)
++{
++}
++
++/* Called from tst-dlclose-lazy-mod2.so.  */
++void
++exported_function (int call_it)
++{
++  if (call_it)
++    /* Previous to the fix this would crash when called during dlclose
++       since symbols from the DSO were no longer available for binding
++       (bug 30425) after the DSO started being closed by dlclose.  */
++    lazily_bound_exported_function ();
++}
+diff --git a/elf/tst-dlclose-lazy-mod2.c b/elf/tst-dlclose-lazy-mod2.c
+new file mode 100644
+index 0000000000000000..767f69ffdb23a685
+--- /dev/null
++++ b/elf/tst-dlclose-lazy-mod2.c
+@@ -0,0 +1,49 @@
++/* Lazy binding during dlclose.  Indirectly loaded module.
++   Copyright (C) 2023 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>
++#include <stdlib.h>
++
++void
++exported_function (int ignored)
++{
++  /* This function is interposed from tst-dlclose-lazy-mod1.so and
++     thus never called.  */
++  abort ();
++}
++
++static void __attribute__ ((constructor))
++init (void)
++{
++  puts ("info: tst-dlclose-lazy-mod2.so constructor called");
++
++  /* Trigger lazy binding to the definition in
++     tst-dlclose-lazy-mod1.so, but not for
++     lazily_bound_exported_function in that module.  */
++  exported_function (0);
++}
++
++static void __attribute__ ((destructor))
++fini (void)
++{
++  puts ("info: tst-dlclose-lazy-mod2.so destructor called");
++
++  /* Trigger the lazily_bound_exported_function call in
++     exported_function in tst-dlclose-lazy-mod1.so.  */
++  exported_function (1);
++}
+diff --git a/elf/tst-dlclose-lazy.c b/elf/tst-dlclose-lazy.c
+new file mode 100644
+index 0000000000000000..976a6bb6f64fa981
+--- /dev/null
++++ b/elf/tst-dlclose-lazy.c
+@@ -0,0 +1,47 @@
++/* Test lazy binding during dlclose (bug 30425).
++   Copyright (C) 2023 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 test re-creates a situation that can arise naturally for C++
++   applications due to the use of vague linkage and differences in the
++   set of compiler-emitted functions.  A function in
++   tst-dlclose-lazy-mod1.so (exported_function) interposes a function
++   in tst-dlclose-lazy-mod2.so.  This function is called from the
++   destructor in tst-dlclose-lazy-mod2.so, after the destructor for
++   tst-dlclose-lazy-mod1.so has already completed.  Prior to the fix
++   for bug 30425, this would lead to a lazy binding failure in
++   tst-dlclose-lazy-mod1.so because dlclose had already marked the DSO
++   as unavailable for binding (by setting l_removed).  */
++
++#include <dlfcn.h>
++#include <support/xdlfcn.h>
++#include <support/check.h>
++
++int
++main (void)
++{
++  /* Load tst-dlclose-lazy-mod1.so, indirectly loading
++     tst-dlclose-lazy-mod2.so.  */
++  void *handle = xdlopen ("tst-dlclose-lazy-mod1.so", RTLD_GLOBAL | RTLD_LAZY);
++
++  /* Invoke the destructor of tst-dlclose-lazy-mod2.so, which calls
++     into tst-dlclose-lazy-mod1.so after its destructor has been
++     called.  */
++  xdlclose (handle);
++
++  return 0;
++}
diff --git a/SPECS/glibc.spec b/SPECS/glibc.spec
index 5e3b50b..328d3ec 100644
--- a/SPECS/glibc.spec
+++ b/SPECS/glibc.spec
@@ -1,6 +1,6 @@
 %define glibcsrcdir glibc-2.28
 %define glibcversion 2.28
-%define glibcrelease 242%{?dist}
+%define glibcrelease 244%{?dist}
 # Pre-release tarballs are pulled in from git using a command that is
 # effectively:
 #
@@ -1056,6 +1056,8 @@ Patch868: glibc-RHEL-3036.patch
 Patch869: glibc-RHEL-3757.patch
 Patch870: glibc-RHEL-2122.patch
 Patch871: glibc-RHEL-1192.patch
+Patch872: glibc-RHEL-3639.patch
+Patch873: glibc-RHEL-10481.patch
 
 # Intel Optimizations
 Patch10001: glibc-sw24097-1.patch
@@ -3002,6 +3004,12 @@ fi
 %files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared
 
 %changelog
+* Mon Nov 20 2023 Florian Weimer <fweimer@redhat.com> - 2.28-244
+- Fix force-first handling in dlclose (RHEL-10481)
+
+* Fri Nov 10 2023 Florian Weimer <fweimer@redhat.com> - 2.28-243
+- Avoid lazy binding failures during dlclose (RHEL-3639)
+
 * Tue Oct 24 2023 Arjun Shankar <arjun@redhat.com> - 2.28-242
 - Add /usr/share/doc/glibc/gai.conf to glibc-doc (RHEL-12894)