diff options
author | Rich Felker <dalias@aerifal.cx> | 2012-10-05 01:15:25 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2012-10-05 01:15:25 -0400 |
commit | 642b7593c3b3488d229488a436bab294dcc27ee9 (patch) | |
tree | 485eb850b836f921c3a4582e2aff8ddf0b01881f /src | |
parent | 99a2af6f45b356324e99acf0da809ca416eed0de (diff) | |
download | musl-642b7593c3b3488d229488a436bab294dcc27ee9.tar.gz musl-642b7593c3b3488d229488a436bab294dcc27ee9.tar.xz musl-642b7593c3b3488d229488a436bab294dcc27ee9.zip |
fix race condition in dlopen
orig_tail was being saved before the lock was obtained, allowing dlopen failure to roll-back other dlopens that had succeeded.
Diffstat (limited to 'src')
-rw-r--r-- | src/ldso/dynlink.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index e09f0715..2bbd492a 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -886,7 +886,7 @@ void *__dynlink(int argc, char **argv) void *dlopen(const char *file, int mode) { - struct dso *volatile p, *orig_tail = tail, *next; + struct dso *volatile p, *orig_tail, *next; size_t i; int cs; @@ -895,6 +895,8 @@ void *dlopen(const char *file, int mode) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); pthread_rwlock_wrlock(&lock); + orig_tail = tail; + if (setjmp(rtld_fail)) { /* Clean up anything new that was (partially) loaded */ if (p->deps) for (i=0; p->deps[i]; i++) |