This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug dynamic-link/13862] New: Reuse of cached stack can cause bounds overrun of thread DTV


http://sourceware.org/bugzilla/show_bug.cgi?id=13862

             Bug #: 13862
           Summary: Reuse of cached stack can cause bounds overrun of
                    thread DTV
           Product: glibc
           Version: 2.14
            Status: NEW
          Severity: normal
          Priority: P2
         Component: dynamic-link
        AssignedTo: unassigned@sourceware.org
        ReportedBy: paul@vineyardnetworks.com
    Classification: Unclassified


Created attachment 6290
  --> http://sourceware.org/bugzilla/attachment.cgi?id=6290
Small program that demonstrates the issue

Platform: Linux/x86_64 (multiple versions including Ubuntu 10, 12, Fedora core
14, Centos 5.5+)

GLIBC versions: tested with 2.7, 2.9, 2.11, 2.14 built from official source

In a program satisfying the conditions listed below, reusing a cached stack
causes a bounds overrun of the thread's DTV structure, leading to a probable
crash.  The _dl_allocate_tls_init function re-initializes the dtv based on the
current slotinfo_list, however it is possible for the dtv to be smaller than
the highest module id loaded.  When this happens the function will write over
memory outside of the dtv, leading to unpredictable behavior and an eventual
crash.

See proposed fix below and attached test-case for repro.

Conditions needed:

The use of a relatively large number of dynamic libraries, loaded at runtime
using dlopen

The use of thread-local-storage within those libraries

A thread exiting prior to the number of loaded libraries increasing a
significant amount, followed by a new thread being created after the number of
libraries has increased.

Example Valgrind output:

==27966== Invalid write of size 8
==27966==    at 0x4010A7A: _dl_allocate_tls_init (dl-tls.c:418)
==27966==    by 0x4E35294: pthread_create@@GLIBC_2.2.5 (allocatestack.c:252)

followed by:
==27966==  Address 0x5b4e6d0 is 0 bytes after a block of size 304 alloc'd
==27966==    at 0x4C26D85: calloc (vg_replace_malloc.c:566)
==27966==    by 0x4010439: allocate_dtv (dl-tls.c:297)
==27966==    by 0x4010B4D: _dl_allocate_tls (dl-tls.c:461)
==27966==    by 0x4E357E9: pthread_create@@GLIBC_2.2.5 (allocatestack.c:575)

Proposed fix:

*** dl-tls.c    2011-05-30 21:12:33.000000000 -0700
--- ../../glibc-2.14.orig/elf/dl-tls.c    2012-03-13 11:29:27.172794002 -0700
***************
*** 406,411 ****
--- 406,415 ----
          /* Unused entry.  */
          continue;

+       /* make sure we don't overrun the currently allocated dtv */
+       if (map->l_tls_modid >= dtv[-1].counter)
+           continue;
+ 
        /* Keep track of the maximum generation number.  This might
           not be the generation counter.  */
        maxgen = MAX (maxgen, listp->slotinfo[cnt].gen);
***************
*** 599,605 ****
          {
            /* 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);
--- 603,609 ----
          {
            /* If this modid was used at some point the memory
               might still be allocated.  */
!           if (total + cnt < dtv[-1].counter && !dtv[total +
cnt].pointer.is_static
                && dtv[total + cnt].pointer.val != TLS_DTV_UNALLOCATED)
              {
                free (dtv[total + cnt].pointer.val);


Reproduction/test case attached.

-- 
Configure bugmail: http://sourceware.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]