[PATCH] ldso: fix dlsym hang when reloading DSOs

Timo Teräs timo.teras at iki.fi
Thu Jun 27 06:34:32 UTC 2013


It can happen under certain cases that the DSO had refcount 0,
but was already loaded. (NODELETE flag is set, or it is pulled
in via both NEEDED dependency and explicit dlopen()).

In these cases we must not re-add the DSO to the global symbol
scope as it is already there. Or we end up corrupting the linked
list and further dlsym lookups will hang.

Signed-off-by: Timo Teräs <timo.teras at iki.fi>
---
 ldso/libdl/libdl.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c
index c451b63..c901512 100644
--- a/ldso/libdl/libdl.c
+++ b/ldso/libdl/libdl.c
@@ -543,15 +543,23 @@ static void *do_dlopen(const char *libname, int flag, ElfW(Addr) from)
 
 #ifdef SHARED
 	/*
-	 * Get the tail of the list.
 	 * In the static case doesn't need to extend the global scope, it is
 	 * ready to be used as it is, because _dl_loaded_modules already points
 	 * to the dlopened library.
+	 *
+	 * Extend the global scope by adding the local scope of the dlopened DSO.
+	 * But only if it's not there. It can happen under certain cases that the
+	 * DSO had refcount = 0, but was already loaded. (NODELETE flag is set, or
+	 * it is pulled in via both NEEDED dependency and explicit dlopen()).
 	 */
-	for (ls = &_dl_loaded_modules->symbol_scope; ls && ls->next; ls = ls->next);
-
-	/* Extend the global scope by adding the local scope of the dlopened DSO. */
-	ls->next = &dyn_chain->dyn->symbol_scope;
+	for (ls = &_dl_loaded_modules->symbol_scope; ; ls = ls->next) {
+		if (ls == &dyn_chain->dyn->symbol_scope)
+			break;
+		if (ls->next == NULL) {
+			ls->next = &dyn_chain->dyn->symbol_scope;
+			break;
+		}
+	}
 #endif
 #ifdef __mips__
 	/*
-- 
1.8.3.1



More information about the uClibc mailing list