Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <aDFdCWTMKj4-79U1@voyager>
Date: Sat, 24 May 2025 07:45:45 +0200
From: Markus Wichmann <nullplan@....net>
To: musl@...ts.openwall.com
Subject: Deadlock in dynamic linker?

Hi all,

I have a question about the handling of shutting_down in the dynamic
linker. Namely, I saw that do_init_fini() will go into an infinite wait
loop if it is set. The idea was probably to park initializing threads
while the system is shutting down, but can't this lead to a deadlock
situation?

I'm thinking something like this: Thread A initializes liba.so. liba.so
has initializers and finalizers, so thread A adds liba.so to the fini
list before calling the initializers. The liba initializer calls
dlopen("libb.so"). libb.so also has initializers.

While thread A is not holding the init_fini_lock, thread B calls exit().
That progresses until __libc_exit_fini() sets shutting_down to 1. Then
it tries to destroy all the libraries, but the loop stops when it comes
to liba.

liba.so has a ctor_visitor, namely thread A, so thread B cannot advance.
Thread A meanwhile is hanging in the infinite wait loop trying to
initialize libb.so. The situation cannot change, and the process hangs
indefinitely.

A simple way out of this pickle could be to add liba.so to the fini list
only after it was initialized. That way, thread B cannot hang on it, or
more generally, the finalizing thread cannot be halted by an incomplete
initialization in another thread. This might change the order of nodes
on the fini list, but only to account for dynamic dependencies. Isn't
that a good thing?

Ciao,
Markus

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.