From 9c9302e51dff9894491ab0ef61738256b286d5ec Mon Sep 17 00:00:00 2001 From: Sebastian Sumpf Date: Thu, 8 Apr 2021 17:29:52 +0200 Subject: [PATCH] ldso: allow symbol resolution during dl_itera_phdr When callback functions of `dl_iterate_phdr` required further jump slot relocations this lead to a deadlock. Therefore, we allow the resolution of further symbols from callback functions, but protect the ELF object list during the iteration, which blocks any dynamic loading (e.g., dlopen/dlcose) of shared object by other threads while in program header iteration. fixes #4071 --- repos/base/src/lib/ldso/exception.cc | 6 +++++- repos/base/src/lib/ldso/include/linker.h | 5 +++++ repos/base/src/lib/ldso/main.cc | 6 ++++++ repos/base/src/lib/ldso/shared_object.cc | 15 ++------------- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/repos/base/src/lib/ldso/exception.cc b/repos/base/src/lib/ldso/exception.cc index 32f96e26cd..4941ca89cc 100644 --- a/repos/base/src/lib/ldso/exception.cc +++ b/repos/base/src/lib/ldso/exception.cc @@ -38,7 +38,8 @@ extern "C" int dl_iterate_phdr(int (*callback) (Phdr_info *info, size_t size, vo int err = 0; Phdr_info info; - Mutex::Guard guard(mutex()); + /* forbid object list manipulation during traversal */ + Mutex::Guard guard(Linker::shared_object_mutex()); for (Object *e = obj_list_head();e; e = e->next_obj()) { @@ -88,6 +89,9 @@ extern "C" unsigned long dl_unwind_find_exidx(unsigned long pc, int *pcount) enum { EXIDX_ENTRY_SIZE = 8 }; *pcount = 0; + /* forbid object list manipulation during traversal */ + Mutex::Guard guard(Linker::shared_object_mutex()); + for (Object *e = obj_list_head(); e; e = e->next_obj()) { /* address of first PT_LOAD header */ diff --git a/repos/base/src/lib/ldso/include/linker.h b/repos/base/src/lib/ldso/include/linker.h index 7ec686aa70..937f113f20 100644 --- a/repos/base/src/lib/ldso/include/linker.h +++ b/repos/base/src/lib/ldso/include/linker.h @@ -129,6 +129,11 @@ namespace Linker { * Global ELF access mutex */ Mutex &mutex(); + + /** + * Mutex that protects shared object list + */ + Mutex &shared_object_mutex(); } diff --git a/repos/base/src/lib/ldso/main.cc b/repos/base/src/lib/ldso/main.cc index e57196dde8..752d793203 100644 --- a/repos/base/src/lib/ldso/main.cc +++ b/repos/base/src/lib/ldso/main.cc @@ -69,6 +69,12 @@ Genode::Mutex &Linker::mutex() } +Genode::Mutex &Linker::shared_object_mutex() +{ + static Mutex _mutex; + return _mutex; +} + /************************************************************** ** ELF object types (shared object, dynamic binaries, ldso ** **************************************************************/ diff --git a/repos/base/src/lib/ldso/shared_object.cc b/repos/base/src/lib/ldso/shared_object.cc index d82edb25ef..6c6798a3ef 100644 --- a/repos/base/src/lib/ldso/shared_object.cc +++ b/repos/base/src/lib/ldso/shared_object.cc @@ -25,17 +25,6 @@ static Linker::Root_object const &to_root(void *h) } -/** - * Needed during shared object creation and destruction, since global lists are - * manipulated - */ -static Genode::Mutex & shared_object_lock() -{ - static Genode::Mutex _lock; - return _lock; -} - - static Linker::Object *find_obj(Genode::addr_t addr) { for (Linker::Object *e = Linker::obj_list_head(); e; e = e->next_obj()) @@ -61,7 +50,7 @@ Genode::Shared_object::Shared_object(Env &env, Allocator &md_alloc, log("LD: open '", file ? file : "binary", "'"); try { - Mutex::Guard guard(shared_object_lock()); + Mutex::Guard guard(Linker::shared_object_mutex()); _handle = new (md_alloc) Root_object(env, md_alloc, file ? file : binary_name(), @@ -121,7 +110,7 @@ Genode::Shared_object::~Shared_object() if (verbose_shared) log("LD: close shared object"); - Mutex::Guard guard(shared_object_lock()); + Mutex::Guard guard(Linker::shared_object_mutex()); destroy(_md_alloc, &const_cast(to_root(_handle))); }