This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug dynamic-link/13862] New: Reuse of cached stack can cause bounds overrun of thread DTV
- From: "paul at vineyardnetworks dot com" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sources dot redhat dot com
- Date: Fri, 16 Mar 2012 22:47:31 +0000
- Subject: [Bug dynamic-link/13862] New: Reuse of cached stack can cause bounds overrun of thread DTV
- Auto-submitted: auto-generated
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.