diff --git a/glibc-rh2023422-1.patch b/glibc-rh2023422-1.patch new file mode 100644 index 0000000..c3ba08e --- /dev/null +++ b/glibc-rh2023422-1.patch @@ -0,0 +1,250 @@ +commit c1cb2deeca1a85c6fc5bd41b90816d48a95bc434 +Author: Florian Weimer +Date: Sun Dec 5 11:28:34 2021 +0100 + + elf: execve statically linked programs instead of crashing [BZ #28648] + + Programs without dynamic dependencies and without a program + interpreter are now run via execve. + + Previously, the dynamic linker either crashed while attempting to + read a non-existing dynamic segment (looking for DT_AUDIT/DT_DEPAUDIT + data), or the self-relocated in the static PIE executable crashed + because the outer dynamic linker had already applied RELRO protection. + + is needed because execve is not available in the + dynamic loader on Hurd. + + Reviewed-by: H.J. Lu + +Conflicts: + elf/Makefile + (usual test differences) + elf/rtld.c + (missing ld.so self-relocation cleanup downstream) + +diff --git a/elf/Makefile b/elf/Makefile +index 118d579c42c38110..7696aa1324919a80 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -224,7 +224,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + tst-tls-ie tst-tls-ie-dlmopen argv0test \ + tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \ + tst-tls20 tst-tls21 tst-dlmopen-dlerror tst-dlmopen-gethostbyname \ +- tst-dl-is_dso tst-ro-dynamic ++ tst-dl-is_dso tst-ro-dynamic \ ++ tst-rtld-run-static \ + # reldep9 + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ +@@ -1914,3 +1915,5 @@ $(objpfx)tst-ro-dynamic-mod.so: $(objpfx)tst-ro-dynamic-mod.os \ + $(LINK.o) -nostdlib -nostartfiles -shared -o $@ \ + -Wl,--script=tst-ro-dynamic-mod.map \ + $(objpfx)tst-ro-dynamic-mod.os ++ ++$(objpfx)tst-rtld-run-static.out: $(objpfx)/ldconfig +diff --git a/elf/rtld.c b/elf/rtld.c +index d83ac1bdc40a6081..6b0d6107801b2f44 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -50,6 +50,7 @@ + #include + #include + #include ++#include + + #include + +@@ -1106,6 +1107,45 @@ load_audit_modules (struct link_map *main_map, struct audit_list *audit_list) + } + } + ++/* Check if the executable is not actualy dynamically linked, and ++ invoke it directly in that case. */ ++static void ++rtld_chain_load (struct link_map *main_map, char *argv0) ++{ ++ /* The dynamic loader run against itself. */ ++ const char *rtld_soname ++ = ((const char *) D_PTR (&GL(dl_rtld_map), l_info[DT_STRTAB]) ++ + GL(dl_rtld_map).l_info[DT_SONAME]->d_un.d_val); ++ if (main_map->l_info[DT_SONAME] != NULL ++ && strcmp (rtld_soname, ++ ((const char *) D_PTR (main_map, l_info[DT_STRTAB]) ++ + main_map->l_info[DT_SONAME]->d_un.d_val)) == 0) ++ _dl_fatal_printf ("%s: loader cannot load itself\n", rtld_soname); ++ ++ /* With DT_NEEDED dependencies, the executable is dynamically ++ linked. */ ++ if (__glibc_unlikely (main_map->l_info[DT_NEEDED] != NULL)) ++ return; ++ ++ /* If the executable has program interpreter, it is dynamically ++ linked. */ ++ for (size_t i = 0; i < main_map->l_phnum; ++i) ++ if (main_map->l_phdr[i].p_type == PT_INTERP) ++ return; ++ ++ const char *pathname = _dl_argv[0]; ++ if (argv0 != NULL) ++ _dl_argv[0] = argv0; ++ int errcode = __rtld_execve (pathname, _dl_argv, _environ); ++ const char *errname = strerrorname_np (errcode); ++ if (errname != NULL) ++ _dl_fatal_printf("%s: cannot execute %s: %s\n", ++ rtld_soname, pathname, errname); ++ else ++ _dl_fatal_printf("%s: cannot execute %s: %d\n", ++ rtld_soname, pathname, errno); ++} ++ + static void + dl_main (const ElfW(Phdr) *phdr, + ElfW(Word) phnum, +@@ -1374,14 +1414,8 @@ dl_main (const ElfW(Phdr) *phdr, + /* Now the map for the main executable is available. */ + main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; + +- if (__glibc_likely (state.mode == rtld_mode_normal) +- && GL(dl_rtld_map).l_info[DT_SONAME] != NULL +- && main_map->l_info[DT_SONAME] != NULL +- && strcmp ((const char *) D_PTR (&GL(dl_rtld_map), l_info[DT_STRTAB]) +- + GL(dl_rtld_map).l_info[DT_SONAME]->d_un.d_val, +- (const char *) D_PTR (main_map, l_info[DT_STRTAB]) +- + main_map->l_info[DT_SONAME]->d_un.d_val) == 0) +- _dl_fatal_printf ("loader cannot load itself\n"); ++ if (__glibc_likely (state.mode == rtld_mode_normal)) ++ rtld_chain_load (main_map, argv0); + + phdr = main_map->l_phdr; + phnum = main_map->l_phnum; +diff --git a/elf/tst-rtld-run-static.c b/elf/tst-rtld-run-static.c +new file mode 100644 +index 0000000000000000..7281093504b675c4 +--- /dev/null ++++ b/elf/tst-rtld-run-static.c +@@ -0,0 +1,62 @@ ++/* Test running statically linked programs using ld.so. ++ Copyright (C) 2021 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 ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ char *ldconfig_path = xasprintf ("%s/elf/ldconfig", support_objdir_root); ++ ++ { ++ char *argv[] = { (char *) "ld.so", ldconfig_path, (char *) "--help", NULL }; ++ struct support_capture_subprocess cap ++ = support_capture_subprogram (support_objdir_elf_ldso, argv); ++ support_capture_subprocess_check (&cap, "no --argv0", 0, sc_allow_stdout); ++ puts ("info: output without --argv0:"); ++ puts (cap.out.buffer); ++ TEST_VERIFY (strstr (cap.out.buffer, "Usage: ldconfig [OPTION...]\n") ++ == cap.out.buffer); ++ support_capture_subprocess_free (&cap); ++ } ++ ++ { ++ char *argv[] = ++ { ++ (char *) "ld.so", (char *) "--argv0", (char *) "ldconfig-argv0", ++ ldconfig_path, (char *) "--help", NULL ++ }; ++ struct support_capture_subprocess cap ++ = support_capture_subprogram (support_objdir_elf_ldso, argv); ++ support_capture_subprocess_check (&cap, "with --argv0", 0, sc_allow_stdout); ++ puts ("info: output with --argv0:"); ++ puts (cap.out.buffer); ++ TEST_VERIFY (strstr (cap.out.buffer, "Usage: ldconfig-argv0 [OPTION...]\n") ++ == cap.out.buffer); ++ support_capture_subprocess_free (&cap); ++ } ++ ++ free (ldconfig_path); ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/generic/dl-execve.h b/sysdeps/generic/dl-execve.h +new file mode 100644 +index 0000000000000000..5fd097df69e1770c +--- /dev/null ++++ b/sysdeps/generic/dl-execve.h +@@ -0,0 +1,25 @@ ++/* execve for the dynamic linker. Generic stub version. ++ Copyright (C) 2021 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 ++ ++static int ++__rtld_execve (const char *path, char *const *argv, char *const *envp) ++{ ++ return ENOSYS; ++} +diff --git a/sysdeps/unix/sysv/linux/dl-execve.h b/sysdeps/unix/sysv/linux/dl-execve.h +new file mode 100644 +index 0000000000000000..ead3e1c28da34363 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/dl-execve.h +@@ -0,0 +1,25 @@ ++/* execve for the dynamic linker. Linux version. ++ Copyright (C) 2021 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 ++ ++static inline int ++__rtld_execve (const char *path, char *const *argv, char *const *envp) ++{ ++ return -INTERNAL_SYSCALL_CALL (execve, path, argv, envp); ++} diff --git a/glibc-rh2023422-2.patch b/glibc-rh2023422-2.patch new file mode 100644 index 0000000..c6d87df --- /dev/null +++ b/glibc-rh2023422-2.patch @@ -0,0 +1,37 @@ +commit 2e75604f8337fa4332977f72a8f6726309679edf +Author: Florian Weimer +Date: Fri Dec 10 16:06:36 2021 +0100 + + elf: Install a symbolic link to ld.so as /usr/bin/ld.so + + This makes ld.so features such as --preload, --audit, + and --list-diagnostics more accessible to end users because they + do not need to know the ABI name of the dynamic loader. + + Reviewed-by: Carlos O'Donell + +diff --git a/elf/Makefile b/elf/Makefile +index 7696aa1324919a80..3e7debdd81baafe0 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -104,7 +104,7 @@ endif + ifeq (yes,$(build-shared)) + extra-objs = $(all-rtld-routines:%=%.os) sofini.os interp.os + generated += librtld.os dl-allobjs.os ld.so ldd +-install-others = $(inst_rtlddir)/$(rtld-installed-name) ++install-others = $(inst_rtlddir)/$(rtld-installed-name) $(inst_bindir)/ld.so + install-bin-script = ldd + endif + +@@ -645,6 +645,11 @@ $(inst_rtlddir)/$(rtld-installed-name): $(objpfx)ld.so $(+force) + $(make-target-directory) + $(do-install-program) + ++# Creates the relative /usr/bin/ld.so symbolic link. ++$(inst_bindir)/ld.so: $(inst_rtlddir)/$(rtld-installed-name) ++ $(make-target-directory) ++ $(make-link) ++ + # Special target called by parent to install just the dynamic linker. + .PHONY: ldso_install + ldso_install: $(inst_rtlddir)/$(rtld-installed-name) diff --git a/glibc-rh2023422-3.patch b/glibc-rh2023422-3.patch new file mode 100644 index 0000000..36f8949 --- /dev/null +++ b/glibc-rh2023422-3.patch @@ -0,0 +1,19 @@ +commit f1eeef945d49c72eb13654bd30b5904e89b4626f +Author: Florian Weimer +Date: Fri Dec 10 21:34:30 2021 +0100 + + elf: Use errcode instead of (unset) errno in rtld_chain_load + +diff --git a/elf/rtld.c b/elf/rtld.c +index 6b0d6107801b2f44..6bbb373c5743cb99 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -1143,7 +1143,7 @@ rtld_chain_load (struct link_map *main_map, char *argv0) + rtld_soname, pathname, errname); + else + _dl_fatal_printf("%s: cannot execute %s: %d\n", +- rtld_soname, pathname, errno); ++ rtld_soname, pathname, errcode); + } + + static void diff --git a/glibc.spec b/glibc.spec index cbf26de..f266a18 100644 --- a/glibc.spec +++ b/glibc.spec @@ -151,7 +151,7 @@ end \ Summary: The GNU libc libraries Name: glibc Version: %{glibcversion} -Release: 11%{?dist} +Release: 12%{?dist} # In general, GPLv2+ is used by programs, LGPLv2+ is used for # libraries. @@ -281,6 +281,9 @@ Patch78: glibc-upstream-2.34-47.patch Patch79: glibc-upstream-2.34-48.patch Patch80: glibc-upstream-2.34-49.patch Patch81: glibc-rh2027789.patch +Patch82: glibc-rh2023422-1.patch +Patch83: glibc-rh2023422-2.patch +Patch84: glibc-rh2023422-3.patch ############################################################################## # Continued list of core "glibc" package information: @@ -2312,6 +2315,9 @@ fi %files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared %changelog +* Fri Dec 10 2021 Florian Weimer - 2.34-12 +- Add /usr/bin/ld.so --list-diagnostics (#2023422) + * Tue Dec 7 2021 Florian Weimer - 2.34-11 - backtrace function crashes without vDSO on ppc64le (#2027789)