]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/glibc/glibc-rh1116050.patch
binutils: Update to version 2.28
[people/pmueller/ipfire-2.x.git] / src / patches / glibc / glibc-rh1116050.patch
CommitLineData
bb330e25
AF
1#
2# Based on this upstream commit:
3#
4# commit d8dd00805b8f3a011735d7a407097fb1c408d867
5# Author: H.J. Lu <hjl.tools@gmail.com>
6# Date: Fri Nov 28 07:54:07 2014 -0800
7#
8# Resize DTV if the current DTV isn't big enough
9#
10# This patch changes _dl_allocate_tls_init to resize DTV if the current DTV
11# isn't big enough. Tested on X86-64, x32 and ia32.
12#
13# [BZ #13862]
14# * elf/dl-tls.c: Include <atomic.h>.
15# (oom): Remove #ifdef SHARED/#endif.
16# (_dl_static_dtv, _dl_initial_dtv): Moved before ...
17# (_dl_resize_dtv): This. Extracted from _dl_update_slotinfo.
18# (_dl_allocate_tls_init): Resize DTV if the current DTV isn't
19# big enough.
20# (_dl_update_slotinfo): Call _dl_resize_dtv to resize DTV.
21# * nptl/Makefile (tests): Add tst-stack4.
22# (modules-names): Add tst-stack4mod.
23# ($(objpfx)tst-stack4): New.
24# (tst-stack4mod.sos): Likewise.
25# ($(objpfx)tst-stack4.out): Likewise.
26# ($(tst-stack4mod.sos)): Likewise.
27# (clean): Likewise.
28# * nptl/tst-stack4.c: New file.
29# * nptl/tst-stack4mod.c: Likewise.
30#
31diff -urN glibc-2.12-2-gc4ccff1/elf/dl-tls.c glibc-2.12-2-gc4ccff1.mod/elf/dl-tls.c
32--- glibc-2.12-2-gc4ccff1/elf/dl-tls.c 2015-02-18 14:15:28.078461873 -0500
33+++ glibc-2.12-2-gc4ccff1.mod/elf/dl-tls.c 2015-02-18 14:38:37.630374771 -0500
34@@ -24,6 +24,7 @@
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <sys/param.h>
38+#include <atomic.h>
39
40 #include <tls.h>
41 #include <dl-tls.h>
42@@ -35,14 +36,12 @@
43
44
45 /* Out-of-memory handler. */
46-#ifdef SHARED
47 static void
48 __attribute__ ((__noreturn__))
49 oom (void)
50 {
51 _dl_fatal_printf ("cannot allocate memory for thread-local data: ABORT\n");
52 }
53-#endif
54
55
56 size_t
57@@ -392,6 +391,52 @@
58 return result;
59 }
60
61+static dtv_t *
62+_dl_resize_dtv (dtv_t *dtv)
63+{
64+ /* Resize the dtv. */
65+ dtv_t *newp;
66+ /* Load GL(dl_tls_max_dtv_idx) atomically since it may be written to by
67+ other threads concurrently. -- We don't have the required atomic
68+ infrastructure to load dl_tls_max_dtv_idx atomically, but on all the
69+ architectures we care about it should load atomically. If this had
70+ an atomic_load_acquire we would still be missing the releases for
71+ the writes. */
72+ size_t newsize = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS;
73+ size_t oldsize = dtv[-1].counter;
74+
75+#if SHARED
76+ if (dtv == GL(dl_initial_dtv))
77+ {
78+ /* This is the initial dtv that was either statically allocated in
79+ __libc_setup_tls or allocated during rtld startup using the
80+ dl-minimal.c malloc instead of the real malloc. We can't free
81+ it, we have to abandon the old storage. */
82+
83+ newp = malloc ((2 + newsize) * sizeof (dtv_t));
84+ if (newp == NULL)
85+ oom ();
86+ memcpy (newp, &dtv[-1], (2 + oldsize) * sizeof (dtv_t));
87+ }
88+ else
89+#endif
90+ {
91+ newp = realloc (&dtv[-1],
92+ (2 + newsize) * sizeof (dtv_t));
93+ if (newp == NULL)
94+ oom ();
95+ }
96+
97+ newp[0].counter = newsize;
98+
99+ /* Clear the newly allocated part. */
100+ memset (newp + 2 + oldsize, '\0',
101+ (newsize - oldsize) * sizeof (dtv_t));
102+
103+ /* Return the generation counter. */
104+ return &newp[1];
105+}
106+
107
108 void *
109 internal_function
110@@ -406,6 +451,16 @@
111 size_t total = 0;
112 size_t maxgen = 0;
113
114+ /* Check if the current dtv is big enough. */
115+ if (dtv[-1].counter < GL(dl_tls_max_dtv_idx))
116+ {
117+ /* Resize the dtv. */
118+ dtv = _dl_resize_dtv (dtv);
119+
120+ /* Install this new dtv in the thread data structures. */
121+ INSTALL_DTV (result, &dtv[-1]);
122+ }
123+
124 /* We have to prepare the dtv for all currently loaded modules using
125 TLS. For those which are dynamically loaded we add the values
126 indicating deferred allocation. */
127@@ -637,41 +692,10 @@
128 assert (total + cnt == modid);
129 if (dtv[-1].counter < modid)
130 {
131- /* Reallocate the dtv. */
132- dtv_t *newp;
133- size_t newsize = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS;
134- size_t oldsize = dtv[-1].counter;
135-
136- assert (map->l_tls_modid <= newsize);
137-
138- if (dtv == GL(dl_initial_dtv))
139- {
140- /* This is the initial dtv that was allocated
141- during rtld startup using the dl-minimal.c
142- malloc instead of the real malloc. We can't
143- free it, we have to abandon the old storage. */
144-
145- newp = malloc ((2 + newsize) * sizeof (dtv_t));
146- if (newp == NULL)
147- oom ();
148- memcpy (newp, &dtv[-1], (2 + oldsize) * sizeof (dtv_t));
149- }
150- else
151- {
152- newp = realloc (&dtv[-1],
153- (2 + newsize) * sizeof (dtv_t));
154- if (newp == NULL)
155- oom ();
156- }
157-
158- newp[0].counter = newsize;
159-
160- /* Clear the newly allocated part. */
161- memset (newp + 2 + oldsize, '\0',
162- (newsize - oldsize) * sizeof (dtv_t));
163+ /* Resize the dtv. */
164+ dtv = _dl_resize_dtv (dtv);
165
166- /* Point dtv to the generation counter. */
167- dtv = &newp[1];
168+ assert (modid <= dtv[-1].counter);
169
170 /* Install this new dtv in the thread data
171 structures. */
172diff -urN glibc-2.12-2-gc4ccff1/nptl/Makefile glibc-2.12-2-gc4ccff1.mod/nptl/Makefile
173--- glibc-2.12-2-gc4ccff1/nptl/Makefile 2015-02-18 14:15:28.073462028 -0500
174+++ glibc-2.12-2-gc4ccff1.mod/nptl/Makefile 2015-02-18 14:15:49.817786667 -0500
175@@ -245,7 +245,7 @@
176 tst-exec1 tst-exec2 tst-exec3 tst-exec4 \
177 tst-exit1 tst-exit2 tst-exit3 \
178 tst-stdio1 tst-stdio2 \
179- tst-stack1 tst-stack2 tst-stack3 \
180+ tst-stack1 tst-stack2 tst-stack3 tst-stack4 \
181 tst-unload \
182 tst-dlsym1 \
183 tst-sysconf \
184@@ -304,7 +304,7 @@
185
186 modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \
187 tst-tls5mod tst-tls5moda tst-tls5modb tst-tls5modc \
188- tst-tls5modd tst-tls5mode tst-tls5modf \
189+ tst-tls5modd tst-tls5mode tst-tls5modf tst-stack4mod \
190 tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod
191 extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) tst-cleanup4aux.o
192 test-extras += $(modules-names)
193@@ -459,6 +459,19 @@
194 $(common-objpfx)malloc/mtrace $(objpfx)tst-stack3.mtrace > $@
195 generated += tst-stack3-mem tst-stack3.mtrace
196
197+$(objpfx)tst-stack4: $(libdl) $(shared-thread-library)
198+tst-stack4mod.sos=$(shell for i in 0 1 2 3 4 5 6 7 8 9 10 \
199+ 11 12 13 14 15 16 17 18 19; do \
200+ for j in 0 1 2 3 4 5 6 7 8 9 10 \
201+ 11 12 13 14 15 16 17 18 19; do \
202+ echo $(objpfx)tst-stack4mod-$$i-$$j.so; \
203+ done; done)
204+$(objpfx)tst-stack4.out: $(tst-stack4mod.sos)
205+$(tst-stack4mod.sos): $(objpfx)tst-stack4mod.so
206+ cp -f $< $@
207+clean:
208+ rm -f $(tst-stack4mod.sos)
209+
210 $(objpfx)tst-cleanup4: $(objpfx)tst-cleanup4aux.o $(shared-thread-library)
211 $(objpfx)tst-cleanupx4: $(objpfx)tst-cleanup4aux.o $(shared-thread-library)
212
213diff -urN glibc-2.12-2-gc4ccff1/nptl/tst-stack4.c glibc-2.12-2-gc4ccff1.mod/nptl/tst-stack4.c
214--- glibc-2.12-2-gc4ccff1/nptl/tst-stack4.c 1969-12-31 19:00:00.000000000 -0500
215+++ glibc-2.12-2-gc4ccff1.mod/nptl/tst-stack4.c 2015-02-18 14:15:49.817786667 -0500
216@@ -0,0 +1,159 @@
217+/* Test DTV size oveflow when pthread_create reuses old DTV and TLS is
218+ used by dlopened shared object.
219+ Copyright (C) 2014 Free Software Foundation, Inc.
220+ This file is part of the GNU C Library.
221+
222+ The GNU C Library is free software; you can redistribute it and/or
223+ modify it under the terms of the GNU Lesser General Public
224+ License as published by the Free Software Foundation; either
225+ version 2.1 of the License, or (at your option) any later version.
226+
227+ The GNU C Library is distributed in the hope that it will be useful,
228+ but WITHOUT ANY WARRANTY; without even the implied warranty of
229+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
230+ Lesser General Public License for more details.
231+
232+ You should have received a copy of the GNU Lesser General Public
233+ License along with the GNU C Library; if not, see
234+ <http://www.gnu.org/licenses/>. */
235+
236+#include <stdio.h>
237+#include <stdint.h>
238+#include <dlfcn.h>
239+#include <assert.h>
240+#include <pthread.h>
241+
242+/* The choices of thread count, and file counts are arbitary.
243+ The point is simply to run enough threads that an exiting
244+ thread has it's stack reused by another thread at the same
245+ time as new libraries have been loaded. */
246+#define DSO_SHARED_FILES 20
247+#define DSO_OPEN_THREADS 20
248+#define DSO_EXEC_THREADS 2
249+
250+/* Used to make sure that only one thread is calling dlopen and dlclose
251+ at a time. */
252+pthread_mutex_t g_lock;
253+
254+typedef void (*function) (void);
255+
256+void *
257+dso_invoke(void *dso_fun)
258+{
259+ function *fun_vec = (function *) dso_fun;
260+ int dso;
261+
262+ for (dso = 0; dso < DSO_SHARED_FILES; dso++)
263+ (*fun_vec[dso]) ();
264+
265+ pthread_exit (NULL);
266+}
267+
268+void *
269+dso_process (void * p)
270+{
271+ void *handle[DSO_SHARED_FILES];
272+ function fun_vec[DSO_SHARED_FILES];
273+ char dso_path[DSO_SHARED_FILES][100];
274+ int dso;
275+ uintptr_t t = (uintptr_t) p;
276+
277+ /* Open DSOs and get a function. */
278+ for (dso = 0; dso < DSO_SHARED_FILES; dso++)
279+ {
280+ sprintf (dso_path[dso], "tst-stack4mod-%i-%i.so", t, dso);
281+
282+ pthread_mutex_lock (&g_lock);
283+
284+ handle[dso] = dlopen (dso_path[dso], RTLD_NOW);
285+ assert (handle[dso]);
286+
287+ fun_vec[dso] = (function) dlsym (handle[dso], "function");
288+ assert (fun_vec[dso]);
289+
290+ pthread_mutex_unlock (&g_lock);
291+ }
292+
293+ /* Spawn workers. */
294+ pthread_t thread[DSO_EXEC_THREADS];
295+ int i, ret;
296+ uintptr_t result = 0;
297+ for (i = 0; i < DSO_EXEC_THREADS; i++)
298+ {
299+ pthread_mutex_lock (&g_lock);
300+ ret = pthread_create (&thread[i], NULL, dso_invoke, (void *) fun_vec);
301+ if (ret != 0)
302+ {
303+ printf ("pthread_create failed: %d\n", ret);
304+ result = 1;
305+ }
306+ pthread_mutex_unlock (&g_lock);
307+ }
308+
309+ if (!result)
310+ for (i = 0; i < DSO_EXEC_THREADS; i++)
311+ {
312+ ret = pthread_join (thread[i], NULL);
313+ if (ret != 0)
314+ {
315+ printf ("pthread_join failed: %d\n", ret);
316+ result = 1;
317+ }
318+ }
319+
320+ /* Close all DSOs. */
321+ for (dso = 0; dso < DSO_SHARED_FILES; dso++)
322+ {
323+ pthread_mutex_lock (&g_lock);
324+ dlclose (handle[dso]);
325+ pthread_mutex_unlock (&g_lock);
326+ }
327+
328+ /* Exit. */
329+ pthread_exit ((void *) result);
330+}
331+
332+static int
333+do_test (void)
334+{
335+ pthread_t thread[DSO_OPEN_THREADS];
336+ int i,j;
337+ int ret;
338+ int result = 0;
339+
340+ pthread_mutex_init (&g_lock, NULL);
341+
342+ /* 100 is arbitrary here and is known to trigger PR 13862. */
343+ for (j = 0; j < 100; j++)
344+ {
345+ for (i = 0; i < DSO_OPEN_THREADS; i++)
346+ {
347+ ret = pthread_create (&thread[i], NULL, dso_process,
348+ (void *) (uintptr_t) i);
349+ if (ret != 0)
350+ {
351+ printf ("pthread_create failed: %d\n", ret);
352+ result = 1;
353+ }
354+ }
355+
356+ if (result)
357+ break;
358+
359+ for (i = 0; i < DSO_OPEN_THREADS; i++)
360+ {
361+ ret = pthread_join (thread[i], NULL);
362+ if (ret != 0)
363+ {
364+ printf ("pthread_join failed: %d\n", ret);
365+ result = 1;
366+ }
367+ }
368+ }
369+
370+ return result;
371+}
372+
373+#define TEST_FUNCTION do_test ()
374+#define TIMEOUT 100
375+#include "../test-skeleton.c"
376diff -urN glibc-2.12-2-gc4ccff1/nptl/tst-stack4mod.c glibc-2.12-2-gc4ccff1.mod/nptl/tst-stack4mod.c
377--- glibc-2.12-2-gc4ccff1/nptl/tst-stack4mod.c 1969-12-31 19:00:00.000000000 -0500
378+++ glibc-2.12-2-gc4ccff1.mod/nptl/tst-stack4mod.c 2015-02-18 14:15:49.817786667 -0500
379@@ -0,0 +1,28 @@
380+/* This tests DTV usage with TLS in dlopened shared object.
381+ Copyright (C) 2014 Free Software Foundation, Inc.
382+ This file is part of the GNU C Library.
383+
384+ The GNU C Library is free software; you can redistribute it and/or
385+ modify it under the terms of the GNU Lesser General Public
386+ License as published by the Free Software Foundation; either
387+ version 2.1 of the License, or (at your option) any later version.
388+
389+ The GNU C Library is distributed in the hope that it will be useful,
390+ but WITHOUT ANY WARRANTY; without even the implied warranty of
391+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
392+ Lesser General Public License for more details.
393+
394+ You should have received a copy of the GNU Lesser General Public
395+ License along with the GNU C Library; if not, see
396+ <http://www.gnu.org/licenses/>. */
397+
398+/* 256 is arbitrary here and is known to trigger PR 13862. */
399+__thread int var[256] attribute_hidden = {0};
400+
401+void
402+function (void)
403+{
404+ int i;
405+ for (i = 0; i < sizeof (var) / sizeof (int); i++)
406+ var[i] = i;
407+}