summaryrefslogtreecommitdiff
path: root/ldso/dynlink.c
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2019-02-25 02:09:36 -0500
committerRich Felker <dalias@aerifal.cx>2019-02-25 02:09:36 -0500
commit6516282d2adfad2c7e66d854cde3357120c75dbd (patch)
tree3abd654ed2dc6a6548f0241df4852e6d75078832 /ldso/dynlink.c
parentba18c1ecc6a18203ad8496791154af86f706f632 (diff)
downloadmusl-6516282d2adfad2c7e66d854cde3357120c75dbd.tar.gz
fix crash in new dynamic tls installation when last dep lacks tls
code introduced in commit 9d44b6460ab603487dab4d916342d9ba4467e6b9 wrongly assumed the dso list tail was the right place to find new dtv storage. however, this is only true if the last-loaded dependency has tls. the correct place to get it is the dso corresponding to the tls module list tail. introduce a container_of macro to get it, and use it. ultimately, dynamic tls allocation should be refactored so that this is not an issue. there is no reason to be allocating new dtv space at each load_library; instead it could happen after all new libraries have been loaded but before they are committed. such changes may be made later, but this commit fixes the present regression.
Diffstat (limited to 'ldso/dynlink.c')
-rw-r--r--ldso/dynlink.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index 025ed1b0..e2c3259f 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -29,6 +29,8 @@ static void error(const char *, ...);
#define MAXP2(a,b) (-(-(a)&-(b)))
#define ALIGN(x,y) ((x)+(y)-1 & -(y))
+#define container_of(p,t,m) ((t*)((char *)(p)-offsetof(t,m)))
+
struct debug {
int ver;
void *head;
@@ -1356,7 +1358,8 @@ static void install_new_tls(void)
{
sigset_t set;
pthread_t self = __pthread_self(), td;
- uintptr_t (*newdtv)[tls_cnt+1] = (void *)tail->new_dtv;
+ struct dso *dtv_provider = container_of(tls_tail, struct dso, tls);
+ uintptr_t (*newdtv)[tls_cnt+1] = (void *)dtv_provider->new_dtv;
struct dso *p;
size_t i, j;
size_t old_cnt = self->dtv[0];