Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
b0be035161 | |||
4d87c64e28 |
88
SOURCES/glibc-RHEL-36147-1.patch
Normal file
88
SOURCES/glibc-RHEL-36147-1.patch
Normal file
@ -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-09 20:22:18.516110414 -0400
|
||||||
|
+++ b/elf/dl-tls.c 2024-08-09 20:23:26.182493188 -0400
|
||||||
|
@@ -553,9 +553,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. */
|
||||||
|
@@ -634,7 +639,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',
|
||||||
|
@@ -662,7 +667,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-09 20:22:18.516110414 -0400
|
||||||
|
+++ b/elf/rtld.c 2024-08-09 20:24:17.584783701 -0400
|
||||||
|
@@ -2478,7 +2478,7 @@ ERROR: '%s': cannot process note segment
|
||||||
|
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-09 20:22:17.808106408 -0400
|
||||||
|
+++ b/nptl/allocatestack.c 2024-08-09 20:25:49.436302396 -0400
|
||||||
|
@@ -244,7 +244,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-09 20:22:18.517110419 -0400
|
||||||
|
+++ b/sysdeps/generic/ldsodefs.h 2024-08-09 20:34:20.093186159 -0400
|
||||||
|
@@ -1185,10 +1185,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. */
|
526
SOURCES/glibc-RHEL-36147-2.patch
Normal file
526
SOURCES/glibc-RHEL-36147-2.patch
Normal file
@ -0,0 +1,526 @@
|
|||||||
|
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 - tests and module-names differences
|
||||||
|
elf/Makefile - add $(libdl) where needed
|
||||||
|
|
||||||
|
diff -Nrup a/elf/Makefile b/elf/Makefile
|
||||||
|
--- a/elf/Makefile 2024-08-09 21:34:38.159713929 -0400
|
||||||
|
+++ b/elf/Makefile 2024-08-16 13:22:32.268485608 -0400
|
||||||
|
@@ -369,6 +369,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 \
|
||||||
|
@@ -720,6 +724,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 \
|
||||||
|
@@ -2775,3 +2782,30 @@ $(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.
|
||||||
|
+$(objpfx)tst-dlopen-tlsreinitmod3.so: $(libdl)
|
||||||
|
+$(objpfx)tst-dlopen-tlsreinit3: $(libdl)
|
||||||
|
+$(objpfx)tst-dlopen-tlsreinitmod1.so: $(libdl)
|
||||||
|
+$(objpfx)tst-dlopen-tlsreinit1: $(libdl)
|
||||||
|
+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-09 21:34:37.782711770 -0400
|
||||||
|
+++ b/elf/dl-open.c 2024-08-13 16:18:12.501292054 -0400
|
||||||
|
@@ -361,17 +361,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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -381,22 +372,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))
|
||||||
|
@@ -408,13 +385,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-09 21:34:38.162713946 -0400
|
||||||
|
+++ b/elf/dl-tls.c 2024-08-13 16:23:19.819877383 -0400
|
||||||
|
@@ -633,17 +633,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;
|
||||||
|
@@ -1100,9 +1104,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. */
|
||||||
|
@@ -1158,5 +1185,8 @@ 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;
|
||||||
|
}
|
||||||
|
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-09 21:57:01.495424018 -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-09 21:59:14.657192089 -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-09 22:00:43.985707332 -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-09 22:01:30.058973079 -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-09 22:02:42.337389978 -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-09 22:03:54.322805189 -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-09 22:07:26.980031781 -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-09 21:34:37.642710968 -0400
|
||||||
|
+++ b/include/link.h 2024-08-09 22:09:03.764585534 -0400
|
||||||
|
@@ -210,6 +210,7 @@ struct link_map
|
||||||
|
unsigned int l_free_initfini:1; /* Nonzero if l_initfini can be
|
||||||
|
freed, ie. not allocated with
|
||||||
|
the dummy malloc in ld.so. */
|
||||||
|
+ 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-09 21:34:38.164713958 -0400
|
||||||
|
+++ b/sysdeps/generic/ldsodefs.h 2024-08-13 16:41:52.398600434 -0400
|
||||||
|
@@ -1218,13 +1218,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
|
16
SOURCES/glibc-RHEL-36147-3.patch
Normal file
16
SOURCES/glibc-RHEL-36147-3.patch
Normal file
@ -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
|
43
SOURCES/glibc-RHEL-39994-1.patch
Normal file
43
SOURCES/glibc-RHEL-39994-1.patch
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
commit afe42e935b3ee97bac9a7064157587777259c60e
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Mon Jun 3 10:49:40 2024 +0200
|
||||||
|
|
||||||
|
elf: Avoid some free (NULL) calls in _dl_update_slotinfo
|
||||||
|
|
||||||
|
This has been confirmed to work around some interposed mallocs. Here
|
||||||
|
is a discussion of the impact test ust/libc-wrapper/test_libc-wrapper
|
||||||
|
in lttng-tools:
|
||||||
|
|
||||||
|
New TLS usage in libgcc_s.so.1, compatibility impact
|
||||||
|
<https://inbox.sourceware.org/libc-alpha/8734v1ieke.fsf@oldenburg.str.redhat.com/>
|
||||||
|
|
||||||
|
Reportedly, this patch also papers over a similar issue when tcmalloc
|
||||||
|
2.9.1 is not compiled with -ftls-model=initial-exec. Of course the
|
||||||
|
goal really should be to compile mallocs with the initial-exec TLS
|
||||||
|
model, but this commit appears to be a useful interim workaround.
|
||||||
|
|
||||||
|
Fixes commit d2123d68275acc0f061e73d5f86ca504e0d5a344 ("elf: Fix slow
|
||||||
|
tls access after dlopen [BZ #19924]").
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
|
||||||
|
index 7b3dd9ab60..670dbc42fc 100644
|
||||||
|
--- a/elf/dl-tls.c
|
||||||
|
+++ b/elf/dl-tls.c
|
||||||
|
@@ -819,7 +819,14 @@ _dl_update_slotinfo (unsigned long int req_modid, size_t new_gen)
|
||||||
|
dtv entry free it. Note: this is not AS-safe. */
|
||||||
|
/* XXX Ideally we will at some point create a memory
|
||||||
|
pool. */
|
||||||
|
- free (dtv[modid].pointer.to_free);
|
||||||
|
+ /* Avoid calling free on a null pointer. Some mallocs
|
||||||
|
+ incorrectly use dynamic TLS, and depending on how the
|
||||||
|
+ free function was compiled, it could call
|
||||||
|
+ __tls_get_addr before the null pointer check in the
|
||||||
|
+ free implementation. Checking here papers over at
|
||||||
|
+ least some dynamic TLS usage by interposed mallocs. */
|
||||||
|
+ if (dtv[modid].pointer.to_free != NULL)
|
||||||
|
+ free (dtv[modid].pointer.to_free);
|
||||||
|
dtv[modid].pointer.val = TLS_DTV_UNALLOCATED;
|
||||||
|
dtv[modid].pointer.to_free = NULL;
|
||||||
|
|
501
SOURCES/glibc-RHEL-39994-2.patch
Normal file
501
SOURCES/glibc-RHEL-39994-2.patch
Normal file
@ -0,0 +1,501 @@
|
|||||||
|
commit 018f0fc3b818d4d1460a4e2384c24802504b1d20
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Mon Jul 1 17:42:04 2024 +0200
|
||||||
|
|
||||||
|
elf: Support recursive use of dynamic TLS in interposed malloc
|
||||||
|
|
||||||
|
It turns out that quite a few applications use bundled mallocs that
|
||||||
|
have been built to use global-dynamic TLS (instead of the recommended
|
||||||
|
initial-exec TLS). The previous workaround from
|
||||||
|
commit afe42e935b3ee97bac9a7064157587777259c60e ("elf: Avoid some
|
||||||
|
free (NULL) calls in _dl_update_slotinfo") does not fix all
|
||||||
|
encountered cases unfortunatelly.
|
||||||
|
|
||||||
|
This change avoids the TLS generation update for recursive use
|
||||||
|
of TLS from a malloc that was called during a TLS update. This
|
||||||
|
is possible because an interposed malloc has a fixed module ID and
|
||||||
|
TLS slot. (It cannot be unloaded.) If an initially-loaded module ID
|
||||||
|
is encountered in __tls_get_addr and the dynamic linker is already
|
||||||
|
in the middle of a TLS update, use the outdated DTV, thus avoiding
|
||||||
|
another call into malloc. It's still necessary to update the
|
||||||
|
DTV to the most recent generation, to get out of the slow path,
|
||||||
|
which is why the check for recursion is needed.
|
||||||
|
|
||||||
|
The bookkeeping is done using a global counter instead of per-thread
|
||||||
|
flag because TLS access in the dynamic linker is tricky.
|
||||||
|
|
||||||
|
All this will go away once the dynamic linker stops using malloc
|
||||||
|
for TLS, likely as part of a change that pre-allocates all TLS
|
||||||
|
during pthread_create/dlopen.
|
||||||
|
|
||||||
|
Fixes commit d2123d68275acc0f061e73d5f86ca504e0d5a344 ("elf: Fix slow
|
||||||
|
tls access after dlopen [BZ #19924]").
|
||||||
|
|
||||||
|
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
elf/Makefile - tests and module-names differences
|
||||||
|
elf/Makefile - add $(libdl) for tst-recursive-tlsmallocmod
|
||||||
|
|
||||||
|
diff -Nrup a/elf/Makefile b/elf/Makefile
|
||||||
|
--- a/elf/Makefile 2024-07-28 20:45:16.055243849 -0400
|
||||||
|
+++ b/elf/Makefile 2024-07-28 20:44:23.446952825 -0400
|
||||||
|
@@ -391,6 +391,7 @@ tests += \
|
||||||
|
tst-nodeps2 \
|
||||||
|
tst-noload \
|
||||||
|
tst-null-argv \
|
||||||
|
+ tst-recursive-tls \
|
||||||
|
tst-relsort1 \
|
||||||
|
tst-rtld-run-static \
|
||||||
|
tst-sonamemove-dlopen \
|
||||||
|
@@ -749,6 +750,23 @@ modules-names = \
|
||||||
|
tst-nodeps1-mod \
|
||||||
|
tst-nodeps2-mod \
|
||||||
|
tst-null-argv-lib \
|
||||||
|
+ tst-recursive-tlsmallocmod \
|
||||||
|
+ tst-recursive-tlsmod0 \
|
||||||
|
+ tst-recursive-tlsmod1 \
|
||||||
|
+ tst-recursive-tlsmod2 \
|
||||||
|
+ tst-recursive-tlsmod3 \
|
||||||
|
+ tst-recursive-tlsmod4 \
|
||||||
|
+ tst-recursive-tlsmod5 \
|
||||||
|
+ tst-recursive-tlsmod6 \
|
||||||
|
+ tst-recursive-tlsmod7 \
|
||||||
|
+ tst-recursive-tlsmod8 \
|
||||||
|
+ tst-recursive-tlsmod9 \
|
||||||
|
+ tst-recursive-tlsmod10 \
|
||||||
|
+ tst-recursive-tlsmod11 \
|
||||||
|
+ tst-recursive-tlsmod12 \
|
||||||
|
+ tst-recursive-tlsmod13 \
|
||||||
|
+ tst-recursive-tlsmod14 \
|
||||||
|
+ tst-recursive-tlsmod15 \
|
||||||
|
tst-relsort1mod1 \
|
||||||
|
tst-relsort1mod2 \
|
||||||
|
tst-sonamemove-linkmod1 \
|
||||||
|
@@ -2358,6 +2376,9 @@ LDLIBS-tst-absolute-zero-lib.so = tst-ab
|
||||||
|
$(objpfx)tst-absolute-zero-lib.so: $(LDLIBS-tst-absolute-zero-lib.so)
|
||||||
|
$(objpfx)tst-absolute-zero: $(objpfx)tst-absolute-zero-lib.so
|
||||||
|
|
||||||
|
+$(objpfx)tst-recursive-tlsmallocmod: $(libdl)
|
||||||
|
+$(objpfx)tst-recursive-tlsmallocmod.so: $(libdl)
|
||||||
|
+
|
||||||
|
# Both the main program and the DSO for tst-libc_dlvsym need to link
|
||||||
|
# against libdl.
|
||||||
|
$(objpfx)tst-libc_dlvsym: $(libdl)
|
||||||
|
@@ -2746,3 +2767,11 @@ CFLAGS-tst-tlsgap-mod0.c += -mtls-dialec
|
||||||
|
CFLAGS-tst-tlsgap-mod1.c += -mtls-dialect=gnu2
|
||||||
|
CFLAGS-tst-tlsgap-mod2.c += -mtls-dialect=gnu2
|
||||||
|
endif
|
||||||
|
+
|
||||||
|
+$(objpfx)tst-recursive-tls: $(objpfx)tst-recursive-tlsmallocmod.so $(libdl)
|
||||||
|
+# More objects than DTV_SURPLUS, to trigger DTV reallocation.
|
||||||
|
+$(objpfx)tst-recursive-tls.out: \
|
||||||
|
+ $(patsubst %,$(objpfx)tst-recursive-tlsmod%.so, \
|
||||||
|
+ 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_$*
|
||||||
|
diff -Nrup a/elf/dl-tls.c b/elf/dl-tls.c
|
||||||
|
--- a/elf/dl-tls.c 2024-07-28 20:45:16.086244021 -0400
|
||||||
|
+++ b/elf/dl-tls.c 2024-07-28 20:44:23.443952808 -0400
|
||||||
|
@@ -71,6 +71,31 @@
|
||||||
|
/* Default for dl_tls_static_optional. */
|
||||||
|
#define OPTIONAL_TLS 512
|
||||||
|
|
||||||
|
+/* Used to count the number of threads currently executing dynamic TLS
|
||||||
|
+ updates. Used to avoid recursive malloc calls in __tls_get_addr
|
||||||
|
+ for an interposed malloc that uses global-dynamic TLS (which is not
|
||||||
|
+ recommended); see _dl_tls_allocate_active checks. This could be a
|
||||||
|
+ per-thread flag, but would need TLS access in the dynamic linker. */
|
||||||
|
+unsigned int _dl_tls_threads_in_update;
|
||||||
|
+
|
||||||
|
+static inline void
|
||||||
|
+_dl_tls_allocate_begin (void)
|
||||||
|
+{
|
||||||
|
+ atomic_fetch_add_relaxed (&_dl_tls_threads_in_update, 1);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline void
|
||||||
|
+_dl_tls_allocate_end (void)
|
||||||
|
+{
|
||||||
|
+ atomic_fetch_add_relaxed (&_dl_tls_threads_in_update, -1);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline bool
|
||||||
|
+_dl_tls_allocate_active (void)
|
||||||
|
+{
|
||||||
|
+ return atomic_load_relaxed (&_dl_tls_threads_in_update) > 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Compute the static TLS surplus based on the namespace count and the
|
||||||
|
TLS space that can be used for optimizations. */
|
||||||
|
static inline int
|
||||||
|
@@ -426,12 +451,18 @@ _dl_allocate_tls_storage (void)
|
||||||
|
size += TLS_PRE_TCB_SIZE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
- /* Perform the allocation. Reserve space for the required alignment
|
||||||
|
- and the pointer to the original allocation. */
|
||||||
|
+ /* Reserve space for the required alignment and the pointer to the
|
||||||
|
+ original allocation. */
|
||||||
|
size_t alignment = GL(dl_tls_static_align);
|
||||||
|
+
|
||||||
|
+ /* Perform the allocation. */
|
||||||
|
+ _dl_tls_allocate_begin ();
|
||||||
|
void *allocated = malloc (size + alignment + sizeof (void *));
|
||||||
|
if (__glibc_unlikely (allocated == NULL))
|
||||||
|
- return NULL;
|
||||||
|
+ {
|
||||||
|
+ _dl_tls_allocate_end ();
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/* Perform alignment and allocate the DTV. */
|
||||||
|
#if TLS_TCB_AT_TP
|
||||||
|
@@ -467,6 +498,8 @@ _dl_allocate_tls_storage (void)
|
||||||
|
result = allocate_dtv (result);
|
||||||
|
if (result == NULL)
|
||||||
|
free (allocated);
|
||||||
|
+
|
||||||
|
+ _dl_tls_allocate_end ();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -484,6 +517,7 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_m
|
||||||
|
size_t newsize = max_modid + DTV_SURPLUS;
|
||||||
|
size_t oldsize = dtv[-1].counter;
|
||||||
|
|
||||||
|
+ _dl_tls_allocate_begin ();
|
||||||
|
if (dtv == GL(dl_initial_dtv))
|
||||||
|
{
|
||||||
|
/* This is the initial dtv that was either statically allocated in
|
||||||
|
@@ -503,6 +537,7 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_m
|
||||||
|
if (newp == NULL)
|
||||||
|
oom ();
|
||||||
|
}
|
||||||
|
+ _dl_tls_allocate_end ();
|
||||||
|
|
||||||
|
newp[0].counter = newsize;
|
||||||
|
|
||||||
|
@@ -677,7 +712,9 @@ allocate_dtv_entry (size_t alignment, si
|
||||||
|
if (powerof2 (alignment) && alignment <= _Alignof (max_align_t))
|
||||||
|
{
|
||||||
|
/* The alignment is supported by malloc. */
|
||||||
|
+ _dl_tls_allocate_begin ();
|
||||||
|
void *ptr = malloc (size);
|
||||||
|
+ _dl_tls_allocate_end ();
|
||||||
|
return (struct dtv_pointer) { ptr, ptr };
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -689,7 +726,10 @@ allocate_dtv_entry (size_t alignment, si
|
||||||
|
|
||||||
|
/* Perform the allocation. This is the pointer we need to free
|
||||||
|
later. */
|
||||||
|
+ _dl_tls_allocate_begin ();
|
||||||
|
void *start = malloc (alloc_size);
|
||||||
|
+ _dl_tls_allocate_end ();
|
||||||
|
+
|
||||||
|
if (start == NULL)
|
||||||
|
return (struct dtv_pointer) {};
|
||||||
|
|
||||||
|
@@ -827,7 +867,11 @@ _dl_update_slotinfo (unsigned long int r
|
||||||
|
free implementation. Checking here papers over at
|
||||||
|
least some dynamic TLS usage by interposed mallocs. */
|
||||||
|
if (dtv[modid].pointer.to_free != NULL)
|
||||||
|
- free (dtv[modid].pointer.to_free);
|
||||||
|
+ {
|
||||||
|
+ _dl_tls_allocate_begin ();
|
||||||
|
+ free (dtv[modid].pointer.to_free);
|
||||||
|
+ _dl_tls_allocate_end ();
|
||||||
|
+ }
|
||||||
|
dtv[modid].pointer.val = TLS_DTV_UNALLOCATED;
|
||||||
|
dtv[modid].pointer.to_free = NULL;
|
||||||
|
|
||||||
|
@@ -957,10 +1001,22 @@ __tls_get_addr (GET_ADDR_ARGS)
|
||||||
|
size_t gen = atomic_load_relaxed (&GL(dl_tls_generation));
|
||||||
|
if (__glibc_unlikely (dtv[0].counter != gen))
|
||||||
|
{
|
||||||
|
- /* Update DTV up to the global generation, see CONCURRENCY NOTES
|
||||||
|
- in _dl_update_slotinfo. */
|
||||||
|
- gen = atomic_load_acquire (&GL(dl_tls_generation));
|
||||||
|
- return update_get_addr (GET_ADDR_PARAM, gen);
|
||||||
|
+ if (_dl_tls_allocate_active ()
|
||||||
|
+ && GET_ADDR_MODULE < _dl_tls_initial_modid_limit)
|
||||||
|
+ /* This is a reentrant __tls_get_addr call, but we can
|
||||||
|
+ satisfy it because it's an initially-loaded module ID.
|
||||||
|
+ These TLS slotinfo slots do not change, so the
|
||||||
|
+ out-of-date generation counter does not matter. However,
|
||||||
|
+ if not in a TLS update, still update_get_addr below, to
|
||||||
|
+ get off the slow path eventually. */
|
||||||
|
+ ;
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ /* Update DTV up to the global generation, see CONCURRENCY NOTES
|
||||||
|
+ in _dl_update_slotinfo. */
|
||||||
|
+ gen = atomic_load_acquire (&GL(dl_tls_generation));
|
||||||
|
+ return update_get_addr (GET_ADDR_PARAM, gen);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
void *p = dtv[GET_ADDR_MODULE].pointer.val;
|
||||||
|
@@ -970,7 +1026,7 @@ __tls_get_addr (GET_ADDR_ARGS)
|
||||||
|
|
||||||
|
return (char *) p + GET_ADDR_OFFSET;
|
||||||
|
}
|
||||||
|
-#endif
|
||||||
|
+#endif /* SHARED */
|
||||||
|
|
||||||
|
|
||||||
|
/* Look up the module's TLS block as for __tls_get_addr,
|
||||||
|
@@ -1019,6 +1075,25 @@ _dl_tls_get_addr_soft (struct link_map *
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
+size_t _dl_tls_initial_modid_limit;
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+_dl_tls_initial_modid_limit_setup (void)
|
||||||
|
+{
|
||||||
|
+ struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list);
|
||||||
|
+ size_t idx;
|
||||||
|
+ for (idx = 0; idx < listp->len; ++idx)
|
||||||
|
+ {
|
||||||
|
+ struct link_map *l = listp->slotinfo[idx].map;
|
||||||
|
+ if (l == NULL
|
||||||
|
+ /* The object can be unloaded, so its modid can be
|
||||||
|
+ reassociated. */
|
||||||
|
+ || !(l->l_type == lt_executable || l->l_type == lt_library))
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ _dl_tls_initial_modid_limit = idx;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
|
||||||
|
void
|
||||||
|
_dl_add_to_slotinfo (struct link_map *l, bool do_add)
|
||||||
|
@@ -1051,9 +1126,11 @@ _dl_add_to_slotinfo (struct link_map *l,
|
||||||
|
the first slot. */
|
||||||
|
assert (idx == 0);
|
||||||
|
|
||||||
|
+ _dl_tls_allocate_begin ();
|
||||||
|
listp = (struct dtv_slotinfo_list *)
|
||||||
|
malloc (sizeof (struct dtv_slotinfo_list)
|
||||||
|
+ TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
|
||||||
|
+ _dl_tls_allocate_end ();
|
||||||
|
if (listp == NULL)
|
||||||
|
{
|
||||||
|
/* We ran out of memory while resizing the dtv slotinfo list. */
|
||||||
|
diff -Nrup a/elf/rtld.c b/elf/rtld.c
|
||||||
|
--- a/elf/rtld.c 2024-07-28 20:45:15.726242029 -0400
|
||||||
|
+++ b/elf/rtld.c 2024-07-28 20:44:23.443952808 -0400
|
||||||
|
@@ -797,6 +797,8 @@ init_tls (size_t naudit)
|
||||||
|
_dl_fatal_printf ("\
|
||||||
|
cannot allocate TLS data structures for initial thread\n");
|
||||||
|
|
||||||
|
+ _dl_tls_initial_modid_limit_setup ();
|
||||||
|
+
|
||||||
|
/* Store for detection of the special case by __tls_get_addr
|
||||||
|
so it knows not to pass this dtv to the normal realloc. */
|
||||||
|
GL(dl_initial_dtv) = GET_DTV (tcbp);
|
||||||
|
diff -Nrup a/elf/tst-recursive-tls.c b/elf/tst-recursive-tls.c
|
||||||
|
--- a/elf/tst-recursive-tls.c 1969-12-31 19:00:00.000000000 -0500
|
||||||
|
+++ b/elf/tst-recursive-tls.c 2024-07-28 20:44:23.443952808 -0400
|
||||||
|
@@ -0,0 +1,60 @@
|
||||||
|
+/* Test with interposed malloc with dynamic TLS.
|
||||||
|
+ 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 <array_length.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/xdlfcn.h>
|
||||||
|
+
|
||||||
|
+/* Defined in tst-recursive-tlsmallocmod.so. */
|
||||||
|
+extern __thread unsigned int malloc_subsytem_counter;
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ /* 16 is large enough to exercise the DTV resizing case. */
|
||||||
|
+ void *handles[16];
|
||||||
|
+
|
||||||
|
+ for (unsigned int i = 0; i < array_length (handles); ++i)
|
||||||
|
+ {
|
||||||
|
+ /* Re-use the TLS slot for module 0. */
|
||||||
|
+ if (i > 0)
|
||||||
|
+ xdlclose (handles[0]);
|
||||||
|
+
|
||||||
|
+ char soname[30];
|
||||||
|
+ snprintf (soname, sizeof (soname), "tst-recursive-tlsmod%u.so", i);
|
||||||
|
+ handles[i] = xdlopen (soname, RTLD_NOW);
|
||||||
|
+
|
||||||
|
+ if (i > 0)
|
||||||
|
+ {
|
||||||
|
+ handles[0] = xdlopen ("tst-recursive-tlsmod0.so", RTLD_NOW);
|
||||||
|
+ int (*fptr) (void) = xdlsym (handles[0], "get_threadvar_0");
|
||||||
|
+ /* May trigger TLS storage allocation using malloc. */
|
||||||
|
+ TEST_COMPARE (fptr (), 0);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (unsigned int i = 0; i < array_length (handles); ++i)
|
||||||
|
+ xdlclose (handles[i]);
|
||||||
|
+
|
||||||
|
+ printf ("info: malloc subsystem calls: %u\n", malloc_subsytem_counter);
|
||||||
|
+ TEST_VERIFY (malloc_subsytem_counter > 0);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff -Nrup a/elf/tst-recursive-tlsmallocmod.c b/elf/tst-recursive-tlsmallocmod.c
|
||||||
|
--- a/elf/tst-recursive-tlsmallocmod.c 1969-12-31 19:00:00.000000000 -0500
|
||||||
|
+++ b/elf/tst-recursive-tlsmallocmod.c 2024-07-28 20:44:23.443952808 -0400
|
||||||
|
@@ -0,0 +1,64 @@
|
||||||
|
+/* Interposed malloc with dynamic TLS.
|
||||||
|
+ 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 <stdlib.h>
|
||||||
|
+#include <dlfcn.h>
|
||||||
|
+
|
||||||
|
+__thread unsigned int malloc_subsytem_counter;
|
||||||
|
+
|
||||||
|
+static __typeof (malloc) *malloc_fptr;
|
||||||
|
+static __typeof (free) *free_fptr;
|
||||||
|
+static __typeof (calloc) *calloc_fptr;
|
||||||
|
+static __typeof (realloc) *realloc_fptr;
|
||||||
|
+
|
||||||
|
+static void __attribute__ ((constructor))
|
||||||
|
+init (void)
|
||||||
|
+{
|
||||||
|
+ malloc_fptr = dlsym (RTLD_NEXT, "malloc");
|
||||||
|
+ free_fptr = dlsym (RTLD_NEXT, "free");
|
||||||
|
+ calloc_fptr = dlsym (RTLD_NEXT, "calloc");
|
||||||
|
+ realloc_fptr = dlsym (RTLD_NEXT, "realloc");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void *
|
||||||
|
+malloc (size_t size)
|
||||||
|
+{
|
||||||
|
+ ++malloc_subsytem_counter;
|
||||||
|
+ return malloc_fptr (size);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+free (void *ptr)
|
||||||
|
+{
|
||||||
|
+ ++malloc_subsytem_counter;
|
||||||
|
+ return free_fptr (ptr);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void *
|
||||||
|
+calloc (size_t a, size_t b)
|
||||||
|
+{
|
||||||
|
+ ++malloc_subsytem_counter;
|
||||||
|
+ return calloc_fptr (a, b);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void *
|
||||||
|
+realloc (void *ptr, size_t size)
|
||||||
|
+{
|
||||||
|
+ ++malloc_subsytem_counter;
|
||||||
|
+ return realloc_fptr (ptr, size);
|
||||||
|
+}
|
||||||
|
diff -Nrup a/elf/tst-recursive-tlsmodN.c b/elf/tst-recursive-tlsmodN.c
|
||||||
|
--- a/elf/tst-recursive-tlsmodN.c 1969-12-31 19:00:00.000000000 -0500
|
||||||
|
+++ b/elf/tst-recursive-tlsmodN.c 2024-07-28 20:44:23.443952808 -0400
|
||||||
|
@@ -0,0 +1,28 @@
|
||||||
|
+/* Test module with global-dynamic TLS. Used to trigger DTV reallocation.
|
||||||
|
+ 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/>. */
|
||||||
|
+
|
||||||
|
+/* Compiled with VAR and FUNC set via -D. FUNC requires some
|
||||||
|
+ relocation against TLS variable VAR. */
|
||||||
|
+
|
||||||
|
+__thread int VAR;
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+FUNC (void)
|
||||||
|
+{
|
||||||
|
+ return VAR;
|
||||||
|
+}
|
||||||
|
diff -Nrup a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
|
||||||
|
--- a/sysdeps/generic/ldsodefs.h 2024-07-28 20:45:15.698241875 -0400
|
||||||
|
+++ b/sysdeps/generic/ldsodefs.h 2024-07-28 20:44:23.444952814 -0400
|
||||||
|
@@ -1235,6 +1235,20 @@ extern struct link_map *_dl_update_sloti
|
||||||
|
size_t gen)
|
||||||
|
attribute_hidden;
|
||||||
|
|
||||||
|
+/* The last TLS module ID that is initially loaded, plus 1. TLS
|
||||||
|
+ addresses for modules with IDs lower than that can be obtained from
|
||||||
|
+ the DTV even if its generation is outdated. */
|
||||||
|
+extern size_t _dl_tls_initial_modid_limit attribute_hidden attribute_relro;
|
||||||
|
+
|
||||||
|
+/* Compute _dl_tls_initial_modid_limit. To be called after initial
|
||||||
|
+ relocation. */
|
||||||
|
+void _dl_tls_initial_modid_limit_setup (void) attribute_hidden;
|
||||||
|
+
|
||||||
|
+/* Number of threads currently in a TLS update. This is used to
|
||||||
|
+ detect reentrant __tls_get_addr calls without a per-thread
|
||||||
|
+ flag. */
|
||||||
|
+extern unsigned int _dl_tls_threads_in_update attribute_hidden;
|
||||||
|
+
|
||||||
|
/* Look up the module's TLS block as for __tls_get_addr,
|
||||||
|
but never touch anything. Return null if it's not allocated yet. */
|
||||||
|
extern void *_dl_tls_get_addr_soft (struct link_map *l) attribute_hidden;
|
||||||
|
diff -Nrup a/sysdeps/x86_64/dl-tls.c b/sysdeps/x86_64/dl-tls.c
|
||||||
|
--- a/sysdeps/x86_64/dl-tls.c 2024-07-28 20:45:15.699241880 -0400
|
||||||
|
+++ b/sysdeps/x86_64/dl-tls.c 2024-07-28 20:44:23.444952814 -0400
|
||||||
|
@@ -41,7 +41,10 @@ __tls_get_addr_slow (GET_ADDR_ARGS)
|
||||||
|
dtv_t *dtv = THREAD_DTV ();
|
||||||
|
|
||||||
|
size_t gen = atomic_load_acquire (&GL(dl_tls_generation));
|
||||||
|
- if (__glibc_unlikely (dtv[0].counter != gen))
|
||||||
|
+ if (__glibc_unlikely (dtv[0].counter != gen)
|
||||||
|
+ /* See comment in __tls_get_addr in elf/dl-tls.c. */
|
||||||
|
+ && !(_dl_tls_allocate_active ()
|
||||||
|
+ && GET_ADDR_MODULE < _dl_tls_initial_modid_limit))
|
||||||
|
return update_get_addr (GET_ADDR_PARAM, gen);
|
||||||
|
|
||||||
|
return tls_get_addr_tail (GET_ADDR_PARAM, dtv, NULL);
|
34
SOURCES/glibc-RHEL-52428-1.patch
Normal file
34
SOURCES/glibc-RHEL-52428-1.patch
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
commit 56e098118a31753a9f755948bb5a47bc7111e214
|
||||||
|
Author: Andreas Schwab <schwab@suse.de>
|
||||||
|
Date: Thu Aug 15 12:14:35 2019 +0200
|
||||||
|
|
||||||
|
Update i386 libm-test-ulps
|
||||||
|
|
||||||
|
Conflicts: ChangeLog removed
|
||||||
|
|
||||||
|
diff --git a/sysdeps/i386/fpu/libm-test-ulps b/sysdeps/i386/fpu/libm-test-ulps
|
||||||
|
index e83bae71b4..2232296fe0 100644
|
||||||
|
--- a/sysdeps/i386/fpu/libm-test-ulps
|
||||||
|
+++ b/sysdeps/i386/fpu/libm-test-ulps
|
||||||
|
@@ -1158,8 +1158,8 @@ float128: 4
|
||||||
|
idouble: 4
|
||||||
|
ifloat: 5
|
||||||
|
ifloat128: 4
|
||||||
|
-ildouble: 7
|
||||||
|
-ldouble: 7
|
||||||
|
+ildouble: 8
|
||||||
|
+ldouble: 8
|
||||||
|
|
||||||
|
Function: Imaginary part of "clog10_upward":
|
||||||
|
double: 2
|
||||||
|
@@ -2222,8 +2222,8 @@ float128: 8
|
||||||
|
idouble: 5
|
||||||
|
ifloat: 5
|
||||||
|
ifloat128: 8
|
||||||
|
-ildouble: 5
|
||||||
|
-ldouble: 5
|
||||||
|
+ildouble: 6
|
||||||
|
+ldouble: 6
|
||||||
|
|
||||||
|
Function: "log":
|
||||||
|
double: 1
|
26
SOURCES/glibc-RHEL-52428-2.patch
Normal file
26
SOURCES/glibc-RHEL-52428-2.patch
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
Author: Patsy Griffin <patsy@redhat.com>
|
||||||
|
|
||||||
|
i386: update ulps
|
||||||
|
|
||||||
|
This change fixes 3 test failures:
|
||||||
|
math/test-ildouble-lgamma
|
||||||
|
math/test-ldouble-finite-lgamma
|
||||||
|
math/test-ldouble-lgamma
|
||||||
|
|
||||||
|
This is a downstream only patch as upstream removed entries for
|
||||||
|
i{float,double,ldouble} by commit: 1c15464ca05f36db5c582856d3770d5e8bde9d61.
|
||||||
|
The ldouble change is already upstream.
|
||||||
|
|
||||||
|
--- a/sysdeps/i386/fpu/libm-test-ulps 2024-08-06 15:51:18.182808710 -0400
|
||||||
|
+++ b/sysdeps/i386/fpu/libm-test-ulps 2024-08-06 18:01:50.579719841 -0400
|
||||||
|
@@ -2030,8 +2030,8 @@ double: 5
|
||||||
|
float: 5
|
||||||
|
idouble: 5
|
||||||
|
ifloat: 5
|
||||||
|
-ildouble: 5
|
||||||
|
-ldouble: 5
|
||||||
|
+ildouble: 6
|
||||||
|
+ldouble: 6
|
||||||
|
|
||||||
|
Function: "hypot":
|
||||||
|
double: 1
|
@ -132,7 +132,7 @@ end \
|
|||||||
Summary: The GNU libc libraries
|
Summary: The GNU libc libraries
|
||||||
Name: glibc
|
Name: glibc
|
||||||
Version: %{glibcversion}
|
Version: %{glibcversion}
|
||||||
Release: %{glibcrelease}.2
|
Release: %{glibcrelease}.5
|
||||||
|
|
||||||
# In general, GPLv2+ is used by programs, LGPLv2+ is used for
|
# In general, GPLv2+ is used by programs, LGPLv2+ is used for
|
||||||
# libraries.
|
# libraries.
|
||||||
@ -1188,6 +1188,13 @@ Patch1000: glibc-RHEL-34264.patch
|
|||||||
Patch1001: glibc-RHEL-34267-1.patch
|
Patch1001: glibc-RHEL-34267-1.patch
|
||||||
Patch1002: glibc-RHEL-34267-2.patch
|
Patch1002: glibc-RHEL-34267-2.patch
|
||||||
Patch1003: glibc-RHEL-34273.patch
|
Patch1003: glibc-RHEL-34273.patch
|
||||||
|
Patch1004: glibc-RHEL-52428-1.patch
|
||||||
|
Patch1005: glibc-RHEL-52428-2.patch
|
||||||
|
Patch1006: glibc-RHEL-39994-1.patch
|
||||||
|
Patch1007: glibc-RHEL-39994-2.patch
|
||||||
|
Patch1008: glibc-RHEL-36147-1.patch
|
||||||
|
Patch1009: glibc-RHEL-36147-2.patch
|
||||||
|
Patch1010: glibc-RHEL-36147-3.patch
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# Continued list of core "glibc" package information:
|
# Continued list of core "glibc" package information:
|
||||||
@ -3019,6 +3026,17 @@ fi
|
|||||||
%files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared
|
%files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Fri Aug 16 2024 Patsy Griffin <patsy@redhat.com> - 2.28-251.5
|
||||||
|
- elf: Clarify and invert second argument of _dl_allocate_tls_init
|
||||||
|
- elf: Avoid re-initializing already allocated TLS in dlopen (RHEL-36147)
|
||||||
|
|
||||||
|
* Thu Aug 8 2024 Patsy Griffin <patsy@redhat.com> - 2.28-251.4
|
||||||
|
- elf: Avoid some free (NULL) calls in _dl_update_slotinfo
|
||||||
|
- elf: Support recursive use of dynamic TLS in interposed malloc (RHEL-39994)
|
||||||
|
|
||||||
|
* Mon Aug 5 2024 Patsy Griffin <patsy@redhat.com> - 2.28-251.3
|
||||||
|
- Update i386 libm-test-ulps (RHEL-52428)
|
||||||
|
|
||||||
* Fri Apr 26 2024 Florian Weimer <fweimer@redhat.com> - 2.28-251.2
|
* Fri Apr 26 2024 Florian Weimer <fweimer@redhat.com> - 2.28-251.2
|
||||||
- CVE-2024-33599: nscd: buffer overflow in netgroup cache (RHEL-34264)
|
- CVE-2024-33599: nscd: buffer overflow in netgroup cache (RHEL-34264)
|
||||||
- CVE-2024-33600: nscd: null pointer dereferences in netgroup cache (RHEL-34267)
|
- CVE-2024-33600: nscd: null pointer dereferences in netgroup cache (RHEL-34267)
|
||||||
|
Loading…
Reference in New Issue
Block a user