about summary refs log tree commit diff
path: root/src/ldso
diff options
context:
space:
mode:
authorSzabolcs Nagy <nsz@port70.net>2015-11-26 19:59:46 +0100
committerRich Felker <dalias@aerifal.cx>2015-11-28 13:34:17 -0500
commit12978acb3066db738c8c15121e81adbb63739876 (patch)
treead1b75f4b307190f31416438b8c6de8494c8f62e /src/ldso
parent8eead3ef18ea71a64ef3cbff8c09bac3b82f1242 (diff)
downloadmusl-12978acb3066db738c8c15121e81adbb63739876.tar.gz
musl-12978acb3066db738c8c15121e81adbb63739876.tar.xz
musl-12978acb3066db738c8c15121e81adbb63739876.zip
ldso: fix the dtv update logic in __tls_get_new
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.
Diffstat (limited to 'src/ldso')
-rw-r--r--src/ldso/dynlink.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c
index 4648e9ac..93e7d67e 100644
--- a/src/ldso/dynlink.c
+++ b/src/ldso/dynlink.c
@@ -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];