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
This commit is contained in:
Sebastian Sumpf 2021-04-08 17:29:52 +02:00 committed by Norman Feske
parent af490bdd5b
commit 9c9302e51d
4 changed files with 18 additions and 14 deletions

View File

@ -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 */

View File

@ -129,6 +129,11 @@ namespace Linker {
* Global ELF access mutex
*/
Mutex &mutex();
/**
* Mutex that protects shared object list
*/
Mutex &shared_object_mutex();
}

View File

@ -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 **
**************************************************************/

View File

@ -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<Root_object &>(to_root(_handle)));
}