Signal la_objopen for ld.so with dlmopen (RHEL-49549)

Resolves: RHEL-49549
This commit is contained in:
Arjun Shankar 2025-07-09 22:50:50 +02:00
parent 7c82c40390
commit 97ea51322d
10 changed files with 831 additions and 1 deletions

55
glibc-RHEL-49549-1.patch Normal file
View File

@ -0,0 +1,55 @@
commit 152f863926e77c6f9c9a8b8779c8084eb844ec44
Author: Andreas Schwab <schwab@suse.de>
Date: Thu Mar 23 16:18:50 2023 +0100
_dl_map_object_from_fd: Remove unnecessary debugger notification in error path
After commit ed3ce71f5c ("elf: Move la_activity (LA_ACT_ADD) after
_dl_add_to_namespace_list() (BZ #28062)") it is no longer necessary to
reset the debugger state in the error case, since the debugger
notification only happens after no more errors can occur.
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 5b0734c816b351f0..98a91d40b74cb76b 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -950,8 +950,6 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
/* Initialize to keep the compiler happy. */
const char *errstring = NULL;
int errval = 0;
- struct r_debug *r = _dl_debug_update (nsid);
- bool make_consistent = false;
/* Get file information. To match the kernel behavior, do not fill
in this information for the executable in case of an explicit
@@ -983,14 +981,6 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
free ((void *) l->l_phdr);
free (l);
free (realname);
-
- if (make_consistent && r != NULL)
- {
- r->r_state = RT_CONSISTENT;
- _dl_debug_state ();
- LIBC_PROBE (map_failed, 2, nsid, r);
- }
-
_dl_signal_error (errval, name, NULL, errstring);
}
@@ -1476,6 +1466,7 @@ cannot enable executable stack as shared object requires");
_dl_add_to_namespace_list (l, nsid);
/* Signal that we are going to add new objects. */
+ struct r_debug *r = _dl_debug_update (nsid);
if (r->r_state == RT_CONSISTENT)
{
#ifdef SHARED
@@ -1492,7 +1483,6 @@ cannot enable executable stack as shared object requires");
r->r_state = RT_ADD;
_dl_debug_state ();
LIBC_PROBE (map_start, 2, nsid, r);
- make_consistent = true;
}
else
assert (r->r_state == RT_ADD);

174
glibc-RHEL-49549-2.patch Normal file
View File

@ -0,0 +1,174 @@
commit ab5aa2ee3d3f978e474803cbbc5fe805ad30e293
Author: Andreas Schwab <schwab@suse.de>
Date: Thu Mar 23 16:46:20 2023 +0100
dlopen: skip debugger notification for DSO loaded from sprof (bug 30258)
Avoid inconsistent state in the debugger interface.
Conflicts:
elf/Makefile: Test differences.
diff --git a/elf/Makefile b/elf/Makefile
index 86d4dd9960088ee1..721f254d121118c0 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -528,6 +528,7 @@ tests-container += \
test-srcs = \
tst-pathopt \
+ tst-sprof-basic \
# tests-srcs
ifeq (yes,$(have-fpie))
@@ -860,6 +861,7 @@ modules-names = \
tst-sonamemove-linkmod1 \
tst-sonamemove-runmod1 \
tst-sonamemove-runmod2 \
+ tst-sprof-mod \
tst-tls19mod1 \
tst-tls19mod2 \
tst-tls19mod3 \
@@ -1114,6 +1116,7 @@ tests-special += \
$(objpfx)tst-rtld-help.out \
$(objpfx)tst-rtld-load-self.out \
$(objpfx)tst-rtld-preload.out \
+ $(objpfx)tst-sprof-basic.out \
# tests-special
endif
tests-special += \
@@ -2946,3 +2949,11 @@ $(objpfx)tst-dlopen-constructor-null: \
$(objpfx)tst-dlopen-constructor-null-mod2.so
$(objpfx)tst-dlopen-constructor-null-mod2.so: \
$(objpfx)tst-dlopen-constructor-null-mod1.so
+
+LDFLAGS-tst-sprof-mod.so = -Wl,-soname,tst-sprof-mod.so
+$(objpfx)tst-sprof-basic: $(objpfx)tst-sprof-mod.so
+$(objpfx)tst-sprof-basic.out: tst-sprof-basic.sh $(objpfx)tst-sprof-basic
+ $(SHELL) $< $(common-objpfx) '$(test-wrapper-env)' \
+ '$(run-program-env)' > $@; \
+ $(evaluate-test)
+generated += tst-sprof-mod.so.profile
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 98a91d40b74cb76b..5c1be6e80cd52e2f 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1465,6 +1465,10 @@ cannot enable executable stack as shared object requires");
/* Now that the object is fully initialized add it to the object list. */
_dl_add_to_namespace_list (l, nsid);
+ /* Skip auditing and debugger notification when called from 'sprof'. */
+ if (mode & __RTLD_SPROF)
+ return l;
+
/* Signal that we are going to add new objects. */
struct r_debug *r = _dl_debug_update (nsid);
if (r->r_state == RT_CONSISTENT)
diff --git a/elf/tst-sprof-basic.c b/elf/tst-sprof-basic.c
new file mode 100644
index 0000000000000000..5e4083305a4acdd6
--- /dev/null
+++ b/elf/tst-sprof-basic.c
@@ -0,0 +1,25 @@
+/* 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/>. */
+
+void hello (void);
+
+int
+main (void)
+{
+ hello ();
+ return 0;
+}
diff --git a/elf/tst-sprof-basic.sh b/elf/tst-sprof-basic.sh
new file mode 100755
index 0000000000000000..901db61708c1b8ec
--- /dev/null
+++ b/elf/tst-sprof-basic.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+# Test basic functionality of sprof
+# 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/>.
+
+set -e
+
+common_objpfx=$1
+test_wrapper_env=$2
+run_program_env=$3
+
+sprof_mod=tst-sprof-mod.so
+
+${test_wrapper_env} \
+${run_program_env} \
+LD_PROFILE=$sprof_mod \
+LD_PROFILE_OUTPUT=${common_objpfx}elf \
+LD_LIBRARY_PATH=${common_objpfx}.:${common_objpfx}elf \
+ ${common_objpfx}elf/ld.so ${common_objpfx}elf/tst-sprof-basic
+
+${test_wrapper_env} \
+${run_program_env} \
+LD_LIBRARY_PATH=${common_objpfx}.:${common_objpfx}elf \
+ ${common_objpfx}elf/ld.so ${common_objpfx}elf/sprof -p $sprof_mod \
+ ${common_objpfx}elf/${sprof_mod}.profile
+
+exit $?
diff --git a/elf/tst-sprof-mod.c b/elf/tst-sprof-mod.c
new file mode 100644
index 0000000000000000..8b3f5e8e07f42ae6
--- /dev/null
+++ b/elf/tst-sprof-mod.c
@@ -0,0 +1,24 @@
+/* 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>
+
+void
+hello (void)
+{
+ printf ("Hello World\n");
+}

30
glibc-RHEL-49549-3.patch Normal file
View File

@ -0,0 +1,30 @@
commit f563971b5bf7191acfdd5702fe00878752c2056d
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Sep 26 11:40:12 2023 +0200
elf: Add dummy declaration of _dl_audit_objclose for !SHARED
This allows us to avoid some #ifdef SHARED conditionals.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 3d9b90a22bfa6a7d..21dbe2d21ed8e605 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1457,7 +1457,14 @@ void DL_ARCH_FIXUP_ATTRIBUTE _dl_audit_pltexit (struct link_map *l,
const void *inregs,
void *outregs)
attribute_hidden;
-#endif /* SHARED */
+
+#else /* !SHARED */
+static inline void
+_dl_audit_objclose (struct link_map *l)
+{
+ /* No audit implementation for !SHARED. */
+}
+#endif /* !SHARED */
#if PTHREAD_IN_LIBC && defined SHARED
/* Recursive locking implementation for use within the dynamic loader.

102
glibc-RHEL-49549-4.patch Normal file
View File

@ -0,0 +1,102 @@
commit ed2b8d3a866eb37e069f6a71bdf10421cd4c5e54
Author: Adam Sampson <ats@offog.org>
Date: Mon May 6 18:16:32 2024 +0100
ldconfig: Move endswithn into a new header file
is_gdb_python_file is doing a similar test, so it can use this helper
function as well.
Signed-off-by: Adam Sampson <ats@offog.org>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/elf/endswith.h b/elf/endswith.h
new file mode 100644
index 0000000000000000..c6430c48be0c1071
--- /dev/null
+++ b/elf/endswith.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 2023-2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <https://www.gnu.org/licenses/>. */
+
+#ifndef _ENDSWITH_H
+#define _ENDSWITH_H
+
+#include <string.h>
+
+/* Return true if the N bytes at NAME end with with the characters in
+ the string SUFFIX. (NAME[N + 1] does not have to be a null byte.)
+ Expected to be called with a string literal for SUFFIX. */
+static inline bool
+endswithn (const char *name, size_t n, const char *suffix)
+{
+ return (n >= strlen (suffix)
+ && memcmp (name + n - strlen (suffix), suffix,
+ strlen (suffix)) == 0);
+}
+
+#endif /* _ENDSWITH_H */
diff --git a/elf/ldconfig.c b/elf/ldconfig.c
index 4a96c409994d96c8..185c8115ae6b4060 100644
--- a/elf/ldconfig.c
+++ b/elf/ldconfig.c
@@ -41,6 +41,7 @@
#include <libgen.h>
#include <ldconfig.h>
+#include <endswith.h>
#include <dl-cache.h>
#include <dl-hwcaps.h>
#include <dl-is_dso.h>
@@ -778,17 +779,6 @@ struct dlib_entry
struct dlib_entry *next;
};
-/* Return true if the N bytes at NAME end with with the characters in
- the string SUFFIX. (NAME[N + 1] does not have to be a null byte.)
- Expected to be called with a string literal for SUFFIX. */
-static inline bool
-endswithn (const char *name, size_t n, const char *suffix)
-{
- return (n >= strlen (suffix)
- && memcmp (name + n - strlen (suffix), suffix,
- strlen (suffix)) == 0);
-}
-
/* Skip some temporary DSO files. These files may be partially written
and lead to ldconfig crashes when examined. */
static bool
diff --git a/elf/readlib.c b/elf/readlib.c
index 8901de2684835653..2701535e3f24a201 100644
--- a/elf/readlib.c
+++ b/elf/readlib.c
@@ -35,6 +35,7 @@
#include <gnu/lib-names.h>
#include <ldconfig.h>
+#include <endswith.h>
#define Elf32_CLASS ELFCLASS32
#define Elf64_CLASS ELFCLASS64
@@ -68,7 +69,7 @@ static bool
is_gdb_python_file (const char *name)
{
size_t len = strlen (name);
- return len > 7 && strcmp (name + len - 7, "-gdb.py") == 0;
+ return endswithn (name, len, "-gdb.py");
}
/* Returns 0 if everything is ok, != 0 in case of error. */

76
glibc-RHEL-49549-5.patch Normal file
View File

@ -0,0 +1,76 @@
commit 4a50fdf8b2c1106b50cd9056b4c6f3a72cdeed5f
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Sep 3 17:52:47 2024 +0200
elf: Update DSO list, write audit log to elf/tst-audit23.out
After commit 1d5024f4f052c12e404d42d3b5bfe9c3e9fd27c4
("support: Build with exceptions and asynchronous unwind tables
[BZ #30587]"), libgcc_s is expected to show up in the DSO
list on 32-bit Arm. Do not update max_objs because vdso is not
tracked (and which is the reason why the test currently passes
even with libgcc_s present).
Also write the log output from the auditor to standard output,
for easier test debugging.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/elf/tst-audit23.c b/elf/tst-audit23.c
index 4904cf1340a97ee1..6ac1f20af60a2ebb 100644
--- a/elf/tst-audit23.c
+++ b/elf/tst-audit23.c
@@ -85,13 +85,28 @@ do_test (int argc, char *argv[])
= support_capture_subprogram (spargv[0], spargv);
support_capture_subprocess_check (&result, "tst-audit22", 0, sc_allow_stderr);
+ {
+ FILE *fp = fmemopen (result.err.buffer, result.err.length, "r");
+ TEST_VERIFY (fp != NULL);
+ unsigned int line = 0;
+ char *buffer = NULL;
+ size_t buffer_length = 0;
+ puts ("info: *** audit log start ***");
+ while (xgetline (&buffer, &buffer_length, fp))
+ printf ("%6u\t%s", ++line, buffer);
+ puts ("info: *** audit log end ***");
+ free (buffer);
+ xfclose (fp);
+ }
+
/* The expected la_objopen/la_objclose:
1. executable
2. loader
3. libc.so
- 4. tst-audit23mod.so
- 5. libc.so (LM_ID_NEWLM).
- 6. vdso (optional and ignored). */
+ 4. libgcc_s.so (one some architectures, for libsupport)
+ 5. tst-audit23mod.so
+ 6. libc.so (LM_ID_NEWLM).
+ vdso (optional and ignored). */
enum { max_objs = 6 };
struct la_obj_t
{
@@ -115,8 +130,10 @@ do_test (int argc, char *argv[])
TEST_VERIFY (out != NULL);
char *buffer = NULL;
size_t buffer_length = 0;
+ unsigned int line = 0;
while (xgetline (&buffer, &buffer_length, out))
{
+ ++line;
if (startswith (buffer, "la_activity: "))
{
uintptr_t cookie;
@@ -174,8 +191,8 @@ do_test (int argc, char *argv[])
if (is_vdso (lname))
continue;
if (nobjs == max_objs)
- FAIL_EXIT1 ("non expected la_objopen: %s %"PRIxPTR" %ld",
- lname, laddr, lmid);
+ FAIL_EXIT1 ("(line %u) non expected la_objopen: %s %"PRIxPTR" %ld",
+ line, lname, laddr, lmid);
objs[nobjs].lname = lname;
objs[nobjs].laddr = laddr;
objs[nobjs].lmid = lmid;

34
glibc-RHEL-49549-6.patch Normal file
View File

@ -0,0 +1,34 @@
commit a20bc2f6233a726c7df8eaa332b6e498bd59321f
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Nov 29 15:36:40 2024 +0100
elf: Add the endswith function to <endswith.h>
And include <stdbool.h> for a definition of bool.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/elf/endswith.h b/elf/endswith.h
index c6430c48be0c1071..3954e57f8eff0faa 100644
--- a/elf/endswith.h
+++ b/elf/endswith.h
@@ -17,6 +17,7 @@
#ifndef _ENDSWITH_H
#define _ENDSWITH_H
+#include <stdbool.h>
#include <string.h>
/* Return true if the N bytes at NAME end with with the characters in
@@ -30,4 +31,11 @@ endswithn (const char *name, size_t n, const char *suffix)
strlen (suffix)) == 0);
}
+/* Same as endswithn, but uses the entire SUBJECT for matching. */
+static inline bool
+endswith (const char *subject, const char *suffix)
+{
+ return endswithn (subject, strlen (subject), suffix);
+}
+
#endif /* _ENDSWITH_H */

131
glibc-RHEL-49549-7.patch Normal file
View File

@ -0,0 +1,131 @@
commit 8f36b1469677afe37168f9af1b77402d7a70c673
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Aug 9 15:31:18 2024 +0200
elf: Signal la_objopen for the proxy link map in dlmopen (bug 31985)
Previously, the ld.so link map was silently added to the namespace.
This change produces an auditing event for it.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 5c1be6e80cd52e2f..6714807946b60188 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -928,6 +928,37 @@ _dl_process_pt_gnu_property (struct link_map *l, int fd, const ElfW(Phdr) *ph)
}
}
+static void
+_dl_notify_new_object (int mode, Lmid_t nsid, struct link_map *l)
+{
+ /* Signal that we are going to add new objects. */
+ struct r_debug *r = _dl_debug_update (nsid);
+ if (r->r_state == RT_CONSISTENT)
+ {
+#ifdef SHARED
+ /* Auditing checkpoint: we are going to add new objects. Since this
+ is called after _dl_add_to_namespace_list the namespace is guaranteed
+ to not be empty. */
+ if ((mode & __RTLD_AUDIT) == 0)
+ _dl_audit_activity_nsid (nsid, LA_ACT_ADD);
+#endif
+
+ /* Notify the debugger we have added some objects. We need to
+ call _dl_debug_initialize in a static program in case dynamic
+ linking has not been used before. */
+ r->r_state = RT_ADD;
+ _dl_debug_state ();
+ LIBC_PROBE (map_start, 2, nsid, r);
+ }
+ else
+ assert (r->r_state == RT_ADD);
+
+#ifdef SHARED
+ /* Auditing checkpoint: we have a new object. */
+ if (!GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing)
+ _dl_audit_objopen (l, nsid);
+#endif
+}
/* Map in the shared object NAME, actually located in REALNAME, and already
opened on FD. */
@@ -1024,6 +1055,8 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
/* Add the map for the mirrored object to the object list. */
_dl_add_to_namespace_list (l, nsid);
+ _dl_notify_new_object (mode, nsid, l);
+
return l;
}
#endif
@@ -1469,33 +1502,7 @@ cannot enable executable stack as shared object requires");
if (mode & __RTLD_SPROF)
return l;
- /* Signal that we are going to add new objects. */
- struct r_debug *r = _dl_debug_update (nsid);
- if (r->r_state == RT_CONSISTENT)
- {
-#ifdef SHARED
- /* Auditing checkpoint: we are going to add new objects. Since this
- is called after _dl_add_to_namespace_list the namespace is guaranteed
- to not be empty. */
- if ((mode & __RTLD_AUDIT) == 0)
- _dl_audit_activity_nsid (nsid, LA_ACT_ADD);
-#endif
-
- /* Notify the debugger we have added some objects. We need to
- call _dl_debug_initialize in a static program in case dynamic
- linking has not been used before. */
- r->r_state = RT_ADD;
- _dl_debug_state ();
- LIBC_PROBE (map_start, 2, nsid, r);
- }
- else
- assert (r->r_state == RT_ADD);
-
-#ifdef SHARED
- /* Auditing checkpoint: we have a new object. */
- if (!GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing)
- _dl_audit_objopen (l, nsid);
-#endif
+ _dl_notify_new_object (mode, nsid, l);
return l;
}
diff --git a/elf/tst-audit23.c b/elf/tst-audit23.c
index 6ac1f20af60a2ebb..0c7ca3112381a31e 100644
--- a/elf/tst-audit23.c
+++ b/elf/tst-audit23.c
@@ -17,6 +17,7 @@
<https://www.gnu.org/licenses/>. */
#include <array_length.h>
+#include <endswith.h>
#include <errno.h>
#include <getopt.h>
#include <link.h>
@@ -106,8 +107,9 @@ do_test (int argc, char *argv[])
4. libgcc_s.so (one some architectures, for libsupport)
5. tst-audit23mod.so
6. libc.so (LM_ID_NEWLM).
+ 7. loader (proxy link map in new namespace)
vdso (optional and ignored). */
- enum { max_objs = 6 };
+ enum { max_objs = 7 };
struct la_obj_t
{
char *lname;
@@ -236,7 +238,9 @@ do_test (int argc, char *argv[])
for (size_t i = 0; i < nobjs; i++)
{
- TEST_COMPARE (objs[i].closed, true);
+ /* This subtest currently does not pass because of bug 32065. */
+ if (! (endswith (objs[i].lname, LD_SO) && objs[i].lmid != LM_ID_BASE))
+ TEST_COMPARE (objs[i].closed, true);
free (objs[i].lname);
}

76
glibc-RHEL-49549-8.patch Normal file
View File

@ -0,0 +1,76 @@
commit c4b160744cb39eca20dc36b39c7fa6e10352706c
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Aug 9 16:06:40 2024 +0200
elf: Call la_objclose for proxy link maps in _dl_fini (bug 32065)
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/elf/dl-fini.c b/elf/dl-fini.c
index fa876da0ffa1cf97..133dbac385b34fbb 100644
--- a/elf/dl-fini.c
+++ b/elf/dl-fini.c
@@ -74,6 +74,7 @@ _dl_fini (void)
unsigned int i;
struct link_map *l;
+ struct link_map *proxy_link_map = NULL;
assert (nloaded != 0 || GL(dl_ns)[ns]._ns_loaded == NULL);
for (l = GL(dl_ns)[ns]._ns_loaded, i = 0; l != NULL; l = l->l_next)
/* Do not handle ld.so in secondary namespaces. */
@@ -89,6 +90,11 @@ _dl_fini (void)
are not dlclose()ed from underneath us. */
++l->l_direct_opencount;
}
+ else
+ /* Used below to call la_objclose for the ld.so proxy
+ link map. */
+ proxy_link_map = l;
+
assert (ns != LM_ID_BASE || i == nloaded);
assert (ns == LM_ID_BASE || i == nloaded || i == nloaded - 1);
unsigned int nmaps = i;
@@ -158,6 +164,9 @@ _dl_fini (void)
--l->l_direct_opencount;
}
+ if (proxy_link_map != NULL)
+ _dl_audit_objclose (proxy_link_map);
+
#ifdef SHARED
_dl_audit_activity_nsid (ns, LA_ACT_CONSISTENT);
#endif
diff --git a/elf/tst-audit23.c b/elf/tst-audit23.c
index 0c7ca3112381a31e..d5137fd44dacde3c 100644
--- a/elf/tst-audit23.c
+++ b/elf/tst-audit23.c
@@ -236,13 +236,26 @@ do_test (int argc, char *argv[])
}
}
+ Lmid_t lmid_other = LM_ID_NEWLM;
+ unsigned int other_namespace_count = 0;
for (size_t i = 0; i < nobjs; i++)
{
- /* This subtest currently does not pass because of bug 32065. */
- if (! (endswith (objs[i].lname, LD_SO) && objs[i].lmid != LM_ID_BASE))
- TEST_COMPARE (objs[i].closed, true);
+ if (objs[i].lmid != LM_ID_BASE)
+ {
+ if (lmid_other == LM_ID_NEWLM)
+ lmid_other = objs[i].lmid;
+ TEST_COMPARE (objs[i].lmid, lmid_other);
+ ++other_namespace_count;
+ if (!(endswith (objs[i].lname, "/" LIBC_SO)
+ || endswith (objs[i].lname, "/" LD_SO)))
+ FAIL ("unexpected object in secondary namespace: %s",
+ objs[i].lname);
+ }
+ TEST_COMPARE (objs[i].closed, true);
free (objs[i].lname);
}
+ /* Both libc.so and ld.so should be present. */
+ TEST_COMPARE (other_namespace_count, 2);
/* la_activity(LA_ACT_CONSISTENT) should be the last callback received.
Since only one link map may be not-CONSISTENT at a time, this also

140
glibc-RHEL-49549-9.patch Normal file
View File

@ -0,0 +1,140 @@
commit 495b96e064da605630a23092d1e484ade4bdc093
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Sep 3 17:57:46 2024 +0200
elf: Reorder audit events in dlcose to match _dl_fini (bug 32066)
This was discovered after extending elf/tst-audit23 to cover
dlclose of the dlmopen namespace.
Auditors already experience the new order during process
shutdown (_dl_fini), so no LAV_CURRENT bump or backwards
compatibility code seems necessary.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/elf/dl-close.c b/elf/dl-close.c
index 8a4c3528a124d4e7..236d89f67f3bf410 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -303,6 +303,12 @@ _dl_close_worker (struct link_map *map, bool force)
}
#ifdef SHARED
+ /* Auditing checkpoint: we will start deleting objects.
+ This is supposed to happen before la_objclose (see _dl_fini),
+ but only once per non-recursive dlclose call. */
+ if (!unload_any)
+ _dl_audit_activity_nsid (nsid, LA_ACT_DELETE);
+
/* Auditing checkpoint: we remove an object. */
_dl_audit_objclose (imap);
#endif
@@ -463,12 +469,8 @@ _dl_close_worker (struct link_map *map, bool force)
if (!unload_any)
goto out;
-#ifdef SHARED
- /* Auditing checkpoint: we will start deleting objects. */
- _dl_audit_activity_nsid (nsid, LA_ACT_DELETE);
-#endif
-
- /* Notify the debugger we are about to remove some loaded objects. */
+ /* Notify the debugger we are about to remove some loaded objects.
+ LA_ACT_DELETE has already been signalled above for !unload_any. */
struct r_debug *r = _dl_debug_update (nsid);
r->r_state = RT_DELETE;
_dl_debug_state ();
diff --git a/elf/tst-audit23.c b/elf/tst-audit23.c
index d5137fd44dacde3c..5e3afd397bb2d3d1 100644
--- a/elf/tst-audit23.c
+++ b/elf/tst-audit23.c
@@ -31,16 +31,21 @@
#include <support/xstdio.h>
#include <support/xdlfcn.h>
#include <support/support.h>
+#include <support/test-driver.h>
static int restart;
+static int do_dlclose;
#define CMDLINE_OPTIONS \
- { "restart", no_argument, &restart, 1 },
+ { "restart", no_argument, &restart, 1 }, \
+ { "dlclose", no_argument, &do_dlclose, 1 }, \
static int
handle_restart (void)
{
xdlopen ("tst-audit23mod.so", RTLD_NOW);
- xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW);
+ void *handle = xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW);
+ if (do_dlclose)
+ xdlclose (handle);
return 0;
}
@@ -60,8 +65,8 @@ is_vdso (const char *str)
|| startswith (str, "linux-vdso");
}
-static int
-do_test (int argc, char *argv[])
+static void
+do_one_test (int argc, char *argv[], bool pass_dlclose_flag)
{
/* We must have either:
- One or four parameters left if called initially:
@@ -69,16 +74,15 @@ do_test (int argc, char *argv[])
+ "--library-path" optional
+ the library path optional
+ the application name */
- if (restart)
- return handle_restart ();
-
- char *spargv[9];
+ char *spargv[10];
TEST_VERIFY_EXIT (((argc - 1) + 3) < array_length (spargv));
int i = 0;
for (; i < argc - 1; i++)
spargv[i] = argv[i + 1];
spargv[i++] = (char *) "--direct";
spargv[i++] = (char *) "--restart";
+ if (pass_dlclose_flag)
+ spargv[i++] = (char *) "--dlclose";
spargv[i] = NULL;
setenv ("LD_AUDIT", "tst-auditmod23.so", 0);
@@ -146,8 +150,14 @@ do_test (int argc, char *argv[])
/* The cookie identifies the object at the head of the link map,
so we only add a new namespace if it changes from the previous
- one. This works since dlmopen is the last in the test body. */
- if (cookie != last_act_cookie && last_act_cookie != -1)
+ one. This works since dlmopen is the last in the test body.
+
+ Currently, this does not work as expected because there
+ is no head link map if a namespace is completely deleted.
+ No LA_ACT_CONSISTENT event is generated in that case.
+ See the comment in _dl_audit_activity_nsid and bug 32068. */
+ if (cookie != last_act_cookie && last_act_cookie != -1
+ && !pass_dlclose_flag)
TEST_COMPARE (last_act, LA_ACT_CONSISTENT);
if (this_act == LA_ACT_ADD && acts[nacts] != cookie)
@@ -265,7 +275,16 @@ do_test (int argc, char *argv[])
free (buffer);
xfclose (out);
+}
+
+static int
+do_test (int argc, char *argv[])
+{
+ if (restart)
+ return handle_restart ();
+ do_one_test (argc, argv, false);
+ do_one_test (argc, argv, true);
return 0;
}

View File

@ -157,7 +157,7 @@ end \
Summary: The GNU libc libraries
Name: glibc
Version: %{glibcversion}
Release: 213%{?dist}
Release: 214%{?dist}
# In general, GPLv2+ is used by programs, LGPLv2+ is used for
# libraries.
@ -1291,6 +1291,15 @@ Patch981: glibc-RHEL-47403-9.patch
Patch982: glibc-RHEL-47403-10.patch
Patch983: glibc-RHEL-47403-11.patch
Patch984: glibc-RHEL-95247.patch
Patch985: glibc-RHEL-49549-1.patch
Patch986: glibc-RHEL-49549-2.patch
Patch987: glibc-RHEL-49549-3.patch
Patch988: glibc-RHEL-49549-4.patch
Patch989: glibc-RHEL-49549-5.patch
Patch990: glibc-RHEL-49549-6.patch
Patch991: glibc-RHEL-49549-7.patch
Patch992: glibc-RHEL-49549-8.patch
Patch993: glibc-RHEL-49549-9.patch
##############################################################################
# Continued list of core "glibc" package information:
@ -3288,6 +3297,9 @@ update_gconv_modules_cache ()
%endif
%changelog
* Wed Jul 09 2025 Arjun Shankar <arjun@redhat.com> - 2.34-214
- Signal la_objopen for ld.so with dlmopen (RHEL-49549)
* Wed Jul 09 2025 Arjun Shankar <arjun@redhat.com> - 2.34-213
- Reduce spurious rebuilds while running tests (RHEL-95247)