From 97ea51322defd337bd9f878cc36183d9ecf65186 Mon Sep 17 00:00:00 2001 From: Arjun Shankar Date: Wed, 9 Jul 2025 22:50:50 +0200 Subject: [PATCH] Signal la_objopen for ld.so with dlmopen (RHEL-49549) Resolves: RHEL-49549 --- glibc-RHEL-49549-1.patch | 55 +++++++++++++ glibc-RHEL-49549-2.patch | 174 +++++++++++++++++++++++++++++++++++++++ glibc-RHEL-49549-3.patch | 30 +++++++ glibc-RHEL-49549-4.patch | 102 +++++++++++++++++++++++ glibc-RHEL-49549-5.patch | 76 +++++++++++++++++ glibc-RHEL-49549-6.patch | 34 ++++++++ glibc-RHEL-49549-7.patch | 131 +++++++++++++++++++++++++++++ glibc-RHEL-49549-8.patch | 76 +++++++++++++++++ glibc-RHEL-49549-9.patch | 140 +++++++++++++++++++++++++++++++ glibc.spec | 14 +++- 10 files changed, 831 insertions(+), 1 deletion(-) create mode 100644 glibc-RHEL-49549-1.patch create mode 100644 glibc-RHEL-49549-2.patch create mode 100644 glibc-RHEL-49549-3.patch create mode 100644 glibc-RHEL-49549-4.patch create mode 100644 glibc-RHEL-49549-5.patch create mode 100644 glibc-RHEL-49549-6.patch create mode 100644 glibc-RHEL-49549-7.patch create mode 100644 glibc-RHEL-49549-8.patch create mode 100644 glibc-RHEL-49549-9.patch diff --git a/glibc-RHEL-49549-1.patch b/glibc-RHEL-49549-1.patch new file mode 100644 index 0000000..299e0fa --- /dev/null +++ b/glibc-RHEL-49549-1.patch @@ -0,0 +1,55 @@ +commit 152f863926e77c6f9c9a8b8779c8084eb844ec44 +Author: Andreas Schwab +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); diff --git a/glibc-RHEL-49549-2.patch b/glibc-RHEL-49549-2.patch new file mode 100644 index 0000000..71ed350 --- /dev/null +++ b/glibc-RHEL-49549-2.patch @@ -0,0 +1,174 @@ +commit ab5aa2ee3d3f978e474803cbbc5fe805ad30e293 +Author: Andreas Schwab +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 ++ . */ ++ ++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 ++# . ++ ++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 ++ . */ ++ ++#include ++ ++void ++hello (void) ++{ ++ printf ("Hello World\n"); ++} diff --git a/glibc-RHEL-49549-3.patch b/glibc-RHEL-49549-3.patch new file mode 100644 index 0000000..e639f93 --- /dev/null +++ b/glibc-RHEL-49549-3.patch @@ -0,0 +1,30 @@ +commit f563971b5bf7191acfdd5702fe00878752c2056d +Author: Florian Weimer +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 + +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. diff --git a/glibc-RHEL-49549-4.patch b/glibc-RHEL-49549-4.patch new file mode 100644 index 0000000..a260ea7 --- /dev/null +++ b/glibc-RHEL-49549-4.patch @@ -0,0 +1,102 @@ +commit ed2b8d3a866eb37e069f6a71bdf10421cd4c5e54 +Author: Adam Sampson +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 + Reviewed-by: Adhemerval Zanella + +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 . */ ++ ++#ifndef _ENDSWITH_H ++#define _ENDSWITH_H ++ ++#include ++ ++/* 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 + + #include ++#include + #include + #include + #include +@@ -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 + + #include ++#include + + #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. */ diff --git a/glibc-RHEL-49549-5.patch b/glibc-RHEL-49549-5.patch new file mode 100644 index 0000000..debfa2a --- /dev/null +++ b/glibc-RHEL-49549-5.patch @@ -0,0 +1,76 @@ +commit 4a50fdf8b2c1106b50cd9056b4c6f3a72cdeed5f +Author: Florian Weimer +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 + +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; diff --git a/glibc-RHEL-49549-6.patch b/glibc-RHEL-49549-6.patch new file mode 100644 index 0000000..b1f2a20 --- /dev/null +++ b/glibc-RHEL-49549-6.patch @@ -0,0 +1,34 @@ +commit a20bc2f6233a726c7df8eaa332b6e498bd59321f +Author: Florian Weimer +Date: Fri Nov 29 15:36:40 2024 +0100 + + elf: Add the endswith function to + + And include for a definition of bool. + + Reviewed-by: Adhemerval Zanella + +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 + #include + + /* 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 */ diff --git a/glibc-RHEL-49549-7.patch b/glibc-RHEL-49549-7.patch new file mode 100644 index 0000000..ebbd1b0 --- /dev/null +++ b/glibc-RHEL-49549-7.patch @@ -0,0 +1,131 @@ +commit 8f36b1469677afe37168f9af1b77402d7a70c673 +Author: Florian Weimer +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 + +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 @@ + . */ + + #include ++#include + #include + #include + #include +@@ -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); + } + diff --git a/glibc-RHEL-49549-8.patch b/glibc-RHEL-49549-8.patch new file mode 100644 index 0000000..5321e52 --- /dev/null +++ b/glibc-RHEL-49549-8.patch @@ -0,0 +1,76 @@ +commit c4b160744cb39eca20dc36b39c7fa6e10352706c +Author: Florian Weimer +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 + +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 diff --git a/glibc-RHEL-49549-9.patch b/glibc-RHEL-49549-9.patch new file mode 100644 index 0000000..8378f44 --- /dev/null +++ b/glibc-RHEL-49549-9.patch @@ -0,0 +1,140 @@ +commit 495b96e064da605630a23092d1e484ade4bdc093 +Author: Florian Weimer +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 + +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 + #include + #include ++#include + + 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; + } + diff --git a/glibc.spec b/glibc.spec index a994311..01bb43e 100644 --- a/glibc.spec +++ b/glibc.spec @@ -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 - 2.34-214 +- Signal la_objopen for ld.so with dlmopen (RHEL-49549) + * Wed Jul 09 2025 Arjun Shankar - 2.34-213 - Reduce spurious rebuilds while running tests (RHEL-95247)