diff options
author | Alan Modra <amodra@gmail.com> | 2011-05-07 21:27:51 -0400 |
---|---|---|
committer | Ulrich Drepper <drepper@gmail.com> | 2011-05-07 21:27:51 -0400 |
commit | 66bdbaa4522f561d4ea90a77af243c004ecf642c (patch) | |
tree | aa509d80595481ac89ee2e000031331908bfc4d4 /elf/dl-close.c | |
parent | c1e9ea3517686173bed4beb07c8bf366c94b8edb (diff) | |
download | glibc-66bdbaa4522f561d4ea90a77af243c004ecf642c.tar.gz glibc-66bdbaa4522f561d4ea90a77af243c004ecf642c.tar.xz glibc-66bdbaa4522f561d4ea90a77af243c004ecf642c.zip |
static tls memory leak on TLS_DTV_AT_TP archs
Diffstat (limited to 'elf/dl-close.c')
-rw-r--r-- | elf/dl-close.c | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/elf/dl-close.c b/elf/dl-close.c index efb2b584f2..229e288ef6 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -591,21 +591,37 @@ _dl_close_worker (struct link_map *map) } } #elif TLS_DTV_AT_TP - if ((size_t) imap->l_tls_offset == tls_free_end) + if (tls_free_start == NO_TLS_OFFSET) + { + tls_free_start = imap->l_tls_firstbyte_offset; + tls_free_end = (imap->l_tls_offset + + imap->l_tls_blocksize); + } + else if (imap->l_tls_firstbyte_offset == tls_free_end) /* Extend the contiguous chunk being reclaimed. */ - tls_free_end -= imap->l_tls_blocksize; + tls_free_end = imap->l_tls_offset + imap->l_tls_blocksize; else if (imap->l_tls_offset + imap->l_tls_blocksize == tls_free_start) /* Extend the chunk backwards. */ - tls_free_start = imap->l_tls_offset; - else + tls_free_start = imap->l_tls_firstbyte_offset; + /* This isn't contiguous with the last chunk freed. + One of them will be leaked unless we can free + one block right away. */ + else if (imap->l_tls_offset + imap->l_tls_blocksize + == GL(dl_tls_static_used)) + GL(dl_tls_static_used) = imap->l_tls_firstbyte_offset; + else if (tls_free_end == GL(dl_tls_static_used)) { - /* This isn't contiguous with the last chunk freed. - One of them will be leaked. */ - if (tls_free_end == GL(dl_tls_static_used)) - GL(dl_tls_static_used) = tls_free_start; - tls_free_start = imap->l_tls_offset; - tls_free_end = tls_free_start + imap->l_tls_blocksize; + GL(dl_tls_static_used) = tls_free_start; + tls_free_start = imap->l_tls_firstbyte_offset; + tls_free_end = imap->l_tls_offset + imap->l_tls_blocksize; + } + else if (tls_free_end < imap->l_tls_firstbyte_offset) + { + /* We pick the later block. It has a chance to + be freed. */ + tls_free_start = imap->l_tls_firstbyte_offset; + tls_free_end = imap->l_tls_offset + imap->l_tls_blocksize; } #else # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" |