diff options
author | Rich Felker <dalias@aerifal.cx> | 2020-09-29 18:42:05 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2020-10-14 20:27:12 -0400 |
commit | 1efc8eb2c7eda7664232ef0292b7283adf0db114 (patch) | |
tree | 3a1780dc7e0bdbaf39b7946995272c66a45681c0 | |
parent | 69a1b39019c51258af14c0b2d836c23d20929c9a (diff) | |
download | musl-1efc8eb2c7eda7664232ef0292b7283adf0db114.tar.gz musl-1efc8eb2c7eda7664232ef0292b7283adf0db114.tar.bz2 musl-1efc8eb2c7eda7664232ef0292b7283adf0db114.tar.xz musl-1efc8eb2c7eda7664232ef0292b7283adf0db114.zip |
fix stale lock when allocation of ctor queue fails during dlopen
queue_ctors should not be called with the init_fini_lock held, since
it may longjmp out on allocation failure. this introduces a minor
TOCTOU race with p->constructed, but one already exists further down
anyway, and by design it's okay to run through the queue more than
once anyway. the only reason we bother to check p->constructed at all
is to avoid spurious failure of dlopen when the library is already
fully loaded and constructed.
-rw-r--r-- | ldso/dynlink.c | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/ldso/dynlink.c b/ldso/dynlink.c index f7474743..15e9e4f9 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -2055,8 +2055,9 @@ void *dlopen(const char *file, int mode) load_deps(p); extend_bfs_deps(p); pthread_mutex_lock(&init_fini_lock); - if (!p->constructed) ctor_queue = queue_ctors(p); + int constructed = p->constructed; pthread_mutex_unlock(&init_fini_lock); + if (!constructed) ctor_queue = queue_ctors(p); if (!p->relocated && (mode & RTLD_LAZY)) { prepare_lazy(p); for (i=0; p->deps[i]; i++) |