Skip to content

Commit d8ae8c6

Browse files
lordrasmuswbx-github
authored andcommitted
ldso: harden _dl_tls_get_addr_soft against an unusable DTV
_dl_tls_get_addr_soft (used to fill dl_phdr_info::dlpi_tls_data) is reached from dl_iterate_phdr, which the unwinder calls during stack unwinding - including pthread cancellation. In such a context the calling thread may have no usable thread pointer / DTV, so THREAD_DTV() can return a near-null bogus pointer and the dtv[-1] dereference faults. This crashed tst-cancel7, where a thread is cancelled inside system(). dlpi_tls_data is optional information for callers such as libsanitizer, so return NULL when the DTV pointer is obviously invalid instead of dereferencing it. Signed-off-by: Ramin Moussavi <ramin.moussavi@yacoub.de>
1 parent 1458f5c commit d8ae8c6

1 file changed

Lines changed: 8 additions & 0 deletions

File tree

ldso/ldso/dl-tls.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -900,7 +900,15 @@ _dl_tls_get_addr_soft (struct link_map *map)
900900
if (map->l_tls_modid == 0)
901901
return NULL;
902902

903+
/* This is called from dl_iterate_phdr to fill dl_phdr_info::dlpi_tls_data,
904+
which the unwinder invokes during stack unwinding (e.g. pthread
905+
cancellation). In such contexts the calling thread may not have a
906+
usable thread pointer / DTV yet (or any more), so THREAD_DTV() can
907+
come back as a near-null bogus pointer. dlpi_tls_data is optional,
908+
so bail out instead of dereferencing it. */
903909
dtv = THREAD_DTV ();
910+
if (dtv == NULL || (uintptr_t) dtv < 4096)
911+
return NULL;
904912
if (map->l_tls_modid > (size_t) dtv[-1].counter)
905913
return NULL;
906914

0 commit comments

Comments
 (0)