[BZ#17090/17620/17621] : fix DTV race, assert, and DTV_SURPLUS Static TLS limit
Commit Message
On Mar 4, 2015, Alan Modra <amodra@gmail.com> wrote:
> On Wed, Mar 04, 2015 at 03:35:29PM +1030, Alan Modra wrote:
>> As does nptl/tst-stack4 on x86_64 if tst-stack4mod.so is built with
>> -mtls-dialect=gnu2.
> This on top of your patch gets me past the segfault in free().
> I now hit another segfault, tst-stack4mod.c:function somehow has
> var == NULL.
Thanks, here's an incremental patch that fixes the attempt to release
the pointer from an entry past the end of the dtv (that you fixed
above); that ensures we don't use, in a TLS Descriptor, the generation
count of an earlier map that used the same dtv slot (this ensures we
update the DTV instead of happily using a NULL pointer in there); and
that silences a -Wundef warning in nptl_db, that I had missed when I
updated the #ifs for the last-posted version of the patch.
I'm now running a full build and test cycle with the combined patch,
that I will post once it (hopefully ;-) completes successfully.
@@ -674,13 +674,17 @@ _dl_update_slotinfo (unsigned long int req_modid)
struct link_map *map = listp->slotinfo[cnt].map;
if (map == NULL)
{
- /* If this modid was used at some point the memory
- might still be allocated. */
- if (! dtv[total + cnt].pointer.is_static
- && dtv[total + cnt].pointer.val != TLS_DTV_UNALLOCATED)
- free (dtv[total + cnt].pointer.val);
- dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED;
- dtv[total + cnt].pointer.is_static = false;
+ if (dtv[-1].counter >= total + cnt)
+ {
+ /* If this modid was used at some point the memory
+ might still be allocated. */
+ if (! dtv[total + cnt].pointer.is_static
+ && (dtv[total + cnt].pointer.val
+ != TLS_DTV_UNALLOCATED))
+ free (dtv[total + cnt].pointer.val);
+ dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED;
+ dtv[total + cnt].pointer.is_static = false;
+ }
continue;
}
@@ -42,7 +42,7 @@ eq_tlsdesc (void *p, void *q)
return tdp->tlsinfo.ti_offset == tdq->tlsinfo.ti_offset;
}
-inline static int
+inline static size_t
map_generation (struct link_map *map)
{
size_t idx = map->l_tls_modid;
@@ -58,7 +58,7 @@ map_generation (struct link_map *map)
we can assume that, if the generation count is zero, we
still haven't determined the generation count for this
module. */
- if (listp->slotinfo[idx].gen)
+ if (listp->slotinfo[idx].map == map && listp->slotinfo[idx].gen)
return listp->slotinfo[idx].gen;
else
break;
@@ -35,7 +35,7 @@
# define DB_RTLD_GLOBAL_FIELD(field) \
DB_STRUCT_FIELD (rtld_global, _##field) \
DB_MAIN_VARIABLE (_##field)
-# elif SHARED
+# elif defined SHARED
# define DB_RTLD_GLOBAL_FIELD(field) \
DB_STRUCT_FIELD (rtld_global, _##field)
# else