ldso: Disallow recursive initialization

Do not support the global construction from of objects from within a global
constructor of another object. This can happen if, for example, dlopen is called
from a global constructor. The construction will be post-boned until the current
constructor has finished.
This commit is contained in:
Sebastian Sumpf 2014-11-24 13:45:46 +01:00 committed by Christian Helmuth
parent 09e6c3457f
commit 038a7999bf
1 changed files with 30 additions and 4 deletions

View File

@ -363,6 +363,7 @@ struct Linker::Elf_object : Object, Genode::List<Elf_object>::Element,
Link_map map;
unsigned ref_count = 1;
unsigned flags = 0;
bool relocated = false;
Elf_object(Dag const *dag) : dynamic(dag)
{ }
@ -408,7 +409,13 @@ struct Linker::Elf_object : Object, Genode::List<Elf_object>::Element,
Link_map::add(&map);
};
virtual void relocate() { dynamic.relocate(); }
virtual void relocate()
{
if (!relocated)
dynamic.relocate();
relocated = true;
}
/**
* Return symbol of given number from ELF
@ -577,6 +584,9 @@ struct Linker::Elf_object : Object, Genode::List<Elf_object>::Element,
*/
struct Init : Genode::List<Elf_object>
{
bool in_progress = false;
bool restart = false;
static Init *list()
{
static Init _list;
@ -619,10 +629,25 @@ struct Init : Genode::List<Elf_object>
obj->relocate();
}
/*
* Recursive initialization call is not allowed here. This might happend
* when Shared_objects (e.g. dlopen and friends) are constructed from within
* global constructors (ctors).
*/
if (in_progress) {
restart = true;
return;
}
in_progress = true;
/* call static constructors */
obj = first();
while (obj) {
Elf_object *next = obj->init_next();
remove(obj);
if (obj->dynamic.init_function) {
if (verbose_relocation)
@ -631,10 +656,11 @@ struct Init : Genode::List<Elf_object>
obj->dynamic.init_function();
}
Elf_object *next = obj->init_next();
remove(obj);
obj = next;
obj = restart ? first() : next;
restart = false;
}
in_progress = false;
}
};