fix regression whereby main thread didn't get TLS relocations
authorRich Felker <dalias@aerifal.cx>
Wed, 14 Aug 2019 01:53:30 +0000 (21:53 -0400)
committerRich Felker <dalias@aerifal.cx>
Wed, 14 Aug 2019 01:53:30 +0000 (21:53 -0400)
commit ffab43602b5900c86b7040abdda8ccf6cdec95f5 broke this by moving
relocations after not only the allocation of storage for the main
thread's static TLS, but after the copying of the TLS image. thus,
relocation results were not reflected in the main thread's copy. this
could be fixed by calling __reset_tls after relocations, but instead
split the allocation and installation before/after relocations so that
there's not a redundant copy.

due to commit 71af5309874269bcc9e4b84ea716fab33d888c1d, updating of
static_tls_cnt needs to be kept with allocation of static TLS, before
relocations, rather than after installation.

ldso/dynlink.c

index a124e70449df987b2bf491275a27740a4c2c1051..7ac0bf7552bc2aac596ec6ffb24f23217714202a 100644 (file)
@@ -1889,13 +1889,25 @@ void __dls3(size_t *sp)
        /* Initial TLS must also be allocated before final relocations
         * might result in calloc being a call to application code. */
        update_tls_size();
+       void *initial_tls = builtin_tls;
        if (libc.tls_size > sizeof builtin_tls || tls_align > MIN_TLS_ALIGN) {
-               void *initial_tls = calloc(libc.tls_size, 1);
+               initial_tls = calloc(libc.tls_size, 1);
                if (!initial_tls) {
                        dprintf(2, "%s: Error getting %zu bytes thread-local storage: %m\n",
                                argv[0], libc.tls_size);
                        _exit(127);
                }
+       }
+       static_tls_cnt = tls_cnt;
+
+       /* The main program must be relocated LAST since it may contain
+        * copy relocations which depend on libraries' relocations. */
+       reloc_all(app.next);
+       reloc_all(&app);
+
+       /* Actual copying to new TLS needs to happen after relocations,
+        * since the TLS images might have contained relocated addresses. */
+       if (initial_tls != builtin_tls) {
                if (__init_tp(__copy_tls(initial_tls)) < 0) {
                        a_crash();
                }
@@ -1909,12 +1921,6 @@ void __dls3(size_t *sp)
                if (__copy_tls((void*)builtin_tls) != self) a_crash();
                libc.tls_size = tmp_tls_size;
        }
-       static_tls_cnt = tls_cnt;
-
-       /* The main program must be relocated LAST since it may contin
-        * copy relocations which depend on libraries' relocations. */
-       reloc_all(app.next);
-       reloc_all(&app);
 
        if (ldso_fail) _exit(127);
        if (ldd_mode) _exit(0);