summaryrefslogtreecommitdiff
path: root/elf-Call-__libc_early_init-for-reused-namespaces-bug.patch
diff options
context:
space:
mode:
Diffstat (limited to 'elf-Call-__libc_early_init-for-reused-namespaces-bug.patch')
-rw-r--r--elf-Call-__libc_early_init-for-reused-namespaces-bug.patch221
1 files changed, 221 insertions, 0 deletions
diff --git a/elf-Call-__libc_early_init-for-reused-namespaces-bug.patch b/elf-Call-__libc_early_init-for-reused-namespaces-bug.patch
new file mode 100644
index 0000000..4985f74
--- /dev/null
+++ b/elf-Call-__libc_early_init-for-reused-namespaces-bug.patch
@@ -0,0 +1,221 @@
+From d0e357ff45a75553dee3b17ed7d303bfa544f6fe Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Fri, 26 Aug 2022 21:15:43 +0200
+Subject: [PATCH] elf: Call __libc_early_init for reused namespaces (bug 29528)
+
+Conflict:adapt context
+Reference:https://sourceware.org/git/?p=glibc.git;a=commit;h=d0e357ff45a75553dee3b17ed7d303bfa544f6fe
+
+libc_map is never reset to NULL, neither during dlclose nor on a
+dlopen call which reuses the namespace structure. As a result, if a
+namespace is reused, its libc is not initialized properly. The most
+visible result is a crash in the <ctype.h> functions.
+
+To prevent similar bugs on namespace reuse from surfacing,
+unconditionally initialize the chosen namespace to zero using memset.
+---
+ elf/Makefile | 7 +++++
+ elf/dl-open.c | 13 ++++++----
+ elf/tst-dlmopen-twice-mod1.c | 37 ++++++++++++++++++++++++++
+ elf/tst-dlmopen-twice-mod2.c | 50 ++++++++++++++++++++++++++++++++++++
+ elf/tst-dlmopen-twice.c | 34 ++++++++++++++++++++++++
+ 5 files changed, 136 insertions(+), 5 deletions(-)
+ create mode 100644 elf/tst-dlmopen-twice-mod1.c
+ create mode 100644 elf/tst-dlmopen-twice-mod2.c
+ create mode 100644 elf/tst-dlmopen-twice.c
+
+diff --git a/elf/Makefile b/elf/Makefile
+index 3928a08787..008770bfaf 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -410,6 +410,7 @@ tests += \
+ tst-dlmopen3 \
+ tst-dlmopen-dlerror \
+ tst-dlmopen-gethostbyname \
++ tst-dlmopen-twice \
+ tst-dlopenfail \
+ tst-dlopenfail-2 \
+ tst-dlopenrpath \
+@@ -839,6 +840,8 @@ modules-names += \
+ tst-dlmopen1mod \
+ tst-dlmopen-dlerror-mod \
+ tst-dlmopen-gethostbyname-mod \
++ tst-dlmopen-twice-mod1 \
++ tst-dlmopen-twice-mod2 \
+ tst-dlopenfaillinkmod \
+ tst-dlopenfailmod1 \
+ tst-dlopenfailmod2 \
+@@ -2976,3 +2979,7 @@ $(objpfx)tst-audit-tlsdesc.out: $(objpfx)tst-auditmod-tlsdesc.so
+ $(LINK.o) -nostdlib -nostartfiles -shared -o $@ \
+ -Wl,--script=tst-ro-dynamic-mod.map \
+ $(objpfx)tst-ro-dynamic-mod.os
++
++$(objpfx)tst-dlmopen-twice.out: \
++ $(objpfx)tst-dlmopen-twice-mod1.so \
++ $(objpfx)tst-dlmopen-twice-mod2.so
+diff --git a/elf/dl-open.c b/elf/dl-open.c
+index a23e65926b..46e8066fd8 100644
+--- a/elf/dl-open.c
++++ b/elf/dl-open.c
+@@ -844,11 +844,14 @@ _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid,
+ _dl_signal_error (EINVAL, file, NULL, N_("\
+ no more namespaces available for dlmopen()"));
+ }
+- else if (nsid == GL(dl_nns))
+- {
+- __rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock);
+- ++GL(dl_nns);
+- }
++
++ if (nsid == GL(dl_nns))
++ ++GL(dl_nns);
++
++ /* Initialize the new namespace. Most members are
++ zero-initialized, only the lock needs special treatment. */
++ memset (&GL(dl_ns)[nsid], 0, sizeof (GL(dl_ns)[nsid]));
++ __rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock);
+
+ _dl_debug_initialize (0, nsid)->r_state = RT_CONSISTENT;
+ }
+diff --git a/elf/tst-dlmopen-twice-mod1.c b/elf/tst-dlmopen-twice-mod1.c
+new file mode 100644
+index 0000000000..0eaf04948c
+--- /dev/null
++++ b/elf/tst-dlmopen-twice-mod1.c
+@@ -0,0 +1,37 @@
++/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Module 1.
++ Copyright (C) 2022 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>
++
++static void __attribute__ ((constructor))
++init (void)
++{
++ puts ("info: tst-dlmopen-twice-mod1.so loaded");
++ fflush (stdout);
++}
++
++static void __attribute__ ((destructor))
++fini (void)
++{
++ puts ("info: tst-dlmopen-twice-mod1.so about to be unloaded");
++ fflush (stdout);
++}
++
++/* Large allocation. The second module does not have this, so it
++ should load libc at a different address. */
++char large_allocate[16 * 1024 * 1024];
+diff --git a/elf/tst-dlmopen-twice-mod2.c b/elf/tst-dlmopen-twice-mod2.c
+new file mode 100644
+index 0000000000..40c6c01f96
+--- /dev/null
++++ b/elf/tst-dlmopen-twice-mod2.c
+@@ -0,0 +1,50 @@
++/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Module 2.
++ Copyright (C) 2022 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 <stdio.h>
++
++static void __attribute__ ((constructor))
++init (void)
++{
++ puts ("info: tst-dlmopen-twice-mod2.so loaded");
++ fflush (stdout);
++}
++
++static void __attribute__ ((destructor))
++fini (void)
++{
++ puts ("info: tst-dlmopen-twice-mod2.so about to be unloaded");
++ fflush (stdout);
++}
++
++int
++run_check (void)
++{
++ puts ("info: about to call isalpha");
++ fflush (stdout);
++
++ volatile char ch = 'a';
++ if (!isalpha (ch))
++ {
++ puts ("error: isalpha ('a') is not true");
++ fflush (stdout);
++ return 1;
++ }
++ return 0;
++}
+diff --git a/elf/tst-dlmopen-twice.c b/elf/tst-dlmopen-twice.c
+new file mode 100644
+index 0000000000..449f3c8fa9
+--- /dev/null
++++ b/elf/tst-dlmopen-twice.c
+@@ -0,0 +1,34 @@
++/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Main.
++ Copyright (C) 2022 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 <support/xdlfcn.h>
++#include <support/check.h>
++
++static int
++do_test (void)
++{
++ void *handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod1.so", RTLD_NOW);
++ xdlclose (handle);
++ handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod2.so", RTLD_NOW);
++ int (*run_check) (void) = xdlsym (handle, "run_check");
++ TEST_COMPARE (run_check (), 0);
++ xdlclose (handle);
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+2.27.0
+