ldso: fix the dtv update logic in __tls_get_new
authorSzabolcs Nagy <nsz@port70.net>
Thu, 26 Nov 2015 18:59:46 +0000 (19:59 +0100)
committerRich Felker <dalias@aerifal.cx>
Sat, 28 Nov 2015 18:34:17 +0000 (13:34 -0500)
if two or more threads accessed tls in a dso that was loaded after
the threads were created, then __tls_get_new could do out-of-bound
memory access (leading to segfault).

accidentally byte count was used instead of element count when
the new dtv pointer was computed. (dso->new_dtv is (void**).)

it is rare that the same dso provides dtv for several threads,
the crash was not observed in practice, but possible to trigger.

src/ldso/dynlink.c

index 4648e9ac33e669c2dd1df9594ab5d0385adb9485..93e7d67e96a59d01f77a2d0a4f473da0b9d0bef8 100644 (file)
@@ -1280,7 +1280,7 @@ void *__tls_get_new(size_t *v)
        /* Get new DTV space from new DSO if needed */
        if (v[0] > (size_t)self->dtv[0]) {
                void **newdtv = p->new_dtv +
-                       (v[0]+1)*sizeof(void *)*a_fetch_add(&p->new_dtv_idx,1);
+                       (v[0]+1)*a_fetch_add(&p->new_dtv_idx,1);
                memcpy(newdtv, self->dtv,
                        ((size_t)self->dtv[0]+1) * sizeof(void *));
                newdtv[0] = (void *)v[0];