]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/glibc/glibc-rh995972.patch
Merge remote-tracking branch 'mfischer/slang' into next
[people/pmueller/ipfire-2.x.git] / src / patches / glibc / glibc-rh995972.patch
1 commit d26dfc60edc8c6dd160eefff16a734152a835ca0
2 Author: Martin von Gagern <Martin.vGagern@gmx.net>
3 Date: Sat May 14 21:25:43 2011 -0400
4
5 Fix handling of static TLS in dlopen'ed objects
6
7 When dynamically loading a library along with several dependencies, calls to
8 _dl_add_to_slotinfo and _dl_update_slotinfo can become intermixed. As a
9 consequence, _dl_update_slotinfo will update the generation counter of the dtv
10 although not all of the slots belonging to that generation have been added.
11 Subsequent calls to _dl_add_to_slotinfo will add more slots to the same
12 generation, for which no storage will be allocated, as the dtv generation
13 checks will claim no work is necessary. This will lead to uninitialized dtv
14 entries and will likely cause a SIGSEGV when thread local variables are
15 accessed.
16
17 diff --git a/elf/Makefile b/elf/Makefile
18 index 8d9657d..6efb86c 100644
19 --- a/elf/Makefile
20 +++ b/elf/Makefile
21 @@ -76,6 +76,7 @@ distribute := rtld-Rules \
22 tst-tlsmod12.c tst-tls10.h tst-alignmod.c tst-alignmod2.c \
23 circlemod1.c circlemod1a.c circlemod2.c circlemod2a.c \
24 circlemod3.c circlemod3a.c nodlopenmod2.c \
25 + tst-tls19mod1.c tst-tls19mod2.c tst-tls19mod3.c \
26 tls-macros.h \
27 reldep8mod1.c reldep8mod2.c reldep8mod3.c \
28 nodel2mod1.c nodel2mod2.c nodel2mod3.c \
29 @@ -194,7 +195,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
30 restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \
31 circleload1 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 tst-tls8 \
32 tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls15 \
33 - tst-tls16 tst-tls17 tst-tls18 tst-tls-dlinfo \
34 + tst-tls16 tst-tls17 tst-tls18 tst-tls19 tst-tls-dlinfo \
35 tst-align tst-align2 $(tests-execstack-$(have-z-execstack)) \
36 tst-dlmodcount tst-dlopenrpath tst-deep1 \
37 tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \
38 @@ -240,6 +241,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
39 $(patsubst %,tst-tlsmod17a%,$(tlsmod17a-suffixes)) \
40 tst-tlsmod17b \
41 $(patsubst %,tst-tlsmod18a%,$(tlsmod18a-suffixes)) \
42 + tst-tls19mod1 tst-tls19mod2 tst-tls19mod3 \
43 circlemod1 circlemod1a circlemod2 circlemod2a \
44 circlemod3 circlemod3a \
45 reldep8mod1 reldep8mod2 reldep8mod3 \
46 @@ -525,6 +527,8 @@ $(objpfx)tst-tlsmod13a.so: $(objpfx)tst-tlsmod13.so
47 # For tst-tls9-static, make sure the modules it dlopens have libc.so in DT_NEEDED
48 $(objpfx)tst-tlsmod5.so: $(common-objpfx)libc.so
49 $(objpfx)tst-tlsmod6.so: $(common-objpfx)libc.so
50 +$(objpfx)tst-tls19mod1.so: $(objpfx)tst-tls19mod2.so $(objpfx)tst-tls19mod3.so
51 +$(objpfx)tst-tls19mod3.so: $(objpfx)ld.so
52 $(objpfx)reldep8mod3.so: $(objpfx)reldep8mod1.so $(objpfx)reldep8mod2.so
53 $(objpfx)nodel2mod3.so: $(objpfx)nodel2mod1.so $(objpfx)nodel2mod2.so
54 $(objpfx)reldep9mod2.so: $(objpfx)reldep9mod1.so
55 @@ -822,6 +826,9 @@ $(patsubst %,$(objpfx)%.os,$(tlsmod18a-modules)): $(objpfx)tst-tlsmod18a%.os : t
56 $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ -DN=$* -DNOT_IN_libc=1 $<
57 $(patsubst %,$(objpfx)tst-tlsmod18a%.so,$(tlsmod18a-suffixes)): $(objpfx)tst-tlsmod18a%.so: $(objpfx)ld.so
58
59 +$(objpfx)tst-tls19: $(libdl)
60 +$(objpfx)tst-tls19.out: $(objpfx)tst-tls19mod1.so
61 +
62 CFLAGS-tst-align.c = $(stack-align-test-flags)
63 CFLAGS-tst-align2.c = $(stack-align-test-flags)
64 CFLAGS-tst-alignmod.c = $(stack-align-test-flags)
65 diff --git a/elf/dl-open.c b/elf/dl-open.c
66 index cf8e8cc..8d90b56 100644
67 --- a/elf/dl-open.c
68 +++ b/elf/dl-open.c
69 @@ -347,6 +347,7 @@ dl_open_worker (void *a)
70 /* If the file is not loaded now as a dependency, add the search
71 list of the newly loaded object to the scope. */
72 bool any_tls = false;
73 + unsigned int first_static_tls = new->l_searchlist.r_nlist;
74 for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
75 {
76 struct link_map *imap = new->l_searchlist.r_list[i];
77 @@ -425,30 +426,9 @@ dl_open_worker (void *a)
78 might have to increase its size. */
79 _dl_add_to_slotinfo (imap);
80
81 - if (imap->l_need_tls_init)
82 - {
83 - /* For static TLS we have to allocate the memory here
84 - and now. This includes allocating memory in the DTV.
85 - But we cannot change any DTV other than our own. So,
86 - if we cannot guarantee that there is room in the DTV
87 - we don't even try it and fail the load.
88 -
89 - XXX We could track the minimum DTV slots allocated in
90 - all threads. */
91 - if (! RTLD_SINGLE_THREAD_P && imap->l_tls_modid > DTV_SURPLUS)
92 - _dl_signal_error (0, "dlopen", NULL, N_("\
93 -cannot load any more object with static TLS"));
94 -
95 - imap->l_need_tls_init = 0;
96 -#ifdef SHARED
97 - /* Update the slot information data for at least the
98 - generation of the DSO we are allocating data for. */
99 - _dl_update_slotinfo (imap->l_tls_modid);
100 -#endif
101 -
102 - GL(dl_init_static_tls) (imap);
103 - assert (imap->l_need_tls_init == 0);
104 - }
105 + if (imap->l_need_tls_init
106 + && first_static_tls == new->l_searchlist.r_nlist)
107 + first_static_tls = i;
108
109 /* We have to bump the generation counter. */
110 any_tls = true;
111 @@ -460,6 +440,40 @@ cannot load any more object with static TLS"));
112 _dl_fatal_printf (N_("\
113 TLS generation counter wrapped! Please report this."));
114
115 + /* We need a second pass for static tls data, because _dl_update_slotinfo
116 + must not be run while calls to _dl_add_to_slotinfo are still pending. */
117 + for (unsigned int i = first_static_tls; i < new->l_searchlist.r_nlist; ++i)
118 + {
119 + struct link_map *imap = new->l_searchlist.r_list[i];
120 +
121 + if (imap->l_need_tls_init
122 + && ! imap->l_init_called
123 + && imap->l_tls_blocksize > 0)
124 + {
125 + /* For static TLS we have to allocate the memory here and
126 + now. This includes allocating memory in the DTV. But we
127 + cannot change any DTV other than our own. So, if we
128 + cannot guarantee that there is room in the DTV we don't
129 + even try it and fail the load.
130 +
131 + XXX We could track the minimum DTV slots allocated in
132 + all threads. */
133 + if (! RTLD_SINGLE_THREAD_P && imap->l_tls_modid > DTV_SURPLUS)
134 + _dl_signal_error (0, "dlopen", NULL, N_("\
135 +cannot load any more object with static TLS"));
136 +
137 + imap->l_need_tls_init = 0;
138 +#ifdef SHARED
139 + /* Update the slot information data for at least the
140 + generation of the DSO we are allocating data for. */
141 + _dl_update_slotinfo (imap->l_tls_modid);
142 +#endif
143 +
144 + GL(dl_init_static_tls) (imap);
145 + assert (imap->l_need_tls_init == 0);
146 + }
147 + }
148 +
149 /* Notify the debugger all new objects have been relocated. */
150 if (relocation_in_progress)
151 LIBC_PROBE (rtld_reloc_complete, 3, args->nsid, r, new);
152 diff --git a/elf/tst-tls19.c b/elf/tst-tls19.c
153 new file mode 100644
154 index 0000000..acbc1d6
155 --- /dev/null
156 +++ b/elf/tst-tls19.c
157 @@ -0,0 +1,27 @@
158 +// BZ 12453
159 +#include <stdio.h>
160 +#include <dlfcn.h>
161 +
162 +
163 +static int
164 +do_test (void)
165 +{
166 + void* dl = dlopen ("tst-tls19mod1.so", RTLD_LAZY | RTLD_GLOBAL);
167 + if (dl == NULL)
168 + {
169 + printf ("Error loading tst-tls19mod1.so: %s\n", dlerror ());
170 + return 1;
171 + }
172 +
173 + int (*fn) (void) = dlsym (dl, "foo");
174 + if (fn == NULL)
175 + {
176 + printf("Error obtaining symbol foo\n");
177 + return 1;
178 + }
179 +
180 + return fn ();
181 +}
182 +
183 +#define TEST_FUNCTION do_test ()
184 +#include "../test-skeleton.c"
185 diff --git a/elf/tst-tls19mod1.c b/elf/tst-tls19mod1.c
186 new file mode 100644
187 index 0000000..2790097
188 --- /dev/null
189 +++ b/elf/tst-tls19mod1.c
190 @@ -0,0 +1,15 @@
191 +#include <stdio.h>
192 +
193 +extern int bar (void);
194 +extern int baz (void);
195 +
196 +int
197 +foo (void)
198 +{
199 + int v1 = bar ();
200 + int v2 = baz ();
201 +
202 + printf ("bar=%d, baz=%d\n", v1, v2);
203 +
204 + return v1 != 666 || v2 != 42;
205 +}
206 diff --git a/elf/tst-tls19mod2.c b/elf/tst-tls19mod2.c
207 new file mode 100644
208 index 0000000..cae702f
209 --- /dev/null
210 +++ b/elf/tst-tls19mod2.c
211 @@ -0,0 +1,13 @@
212 +static int __thread tbar __attribute__ ((tls_model ("initial-exec"))) = 666;
213 +
214 +void
215 +setter (int a)
216 +{
217 + tbar = a;
218 +}
219 +
220 +int
221 +bar (void)
222 +{
223 + return tbar;
224 +}
225 diff --git a/elf/tst-tls19mod3.c b/elf/tst-tls19mod3.c
226 new file mode 100644
227 index 0000000..e7b2801
228 --- /dev/null
229 +++ b/elf/tst-tls19mod3.c
230 @@ -0,0 +1,16 @@
231 +#include <stdio.h>
232 +
233 +static int __thread tbaz __attribute__ ((tls_model ("local-dynamic"))) = 42;
234 +
235 +void
236 +setter2 (int a)
237 +{
238 + tbaz = a;
239 +}
240 +
241 +int
242 +baz (void)
243 +{
244 + printf ("&tbaz=%p\n", &tbaz);
245 + return tbaz;
246 +}