]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/glibc/glibc-rh1116050.patch
dhcpcd: fix delay after dhcp down.
[ipfire-2.x.git] / src / patches / glibc / glibc-rh1116050.patch
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 #
31 diff -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. */
172 diff -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
213 diff -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"
376 diff -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 +}