From 038a7999bf8264ff37234887bf9f18b2ca30116f Mon Sep 17 00:00:00 2001 From: Sebastian Sumpf Date: Mon, 24 Nov 2014 13:45:46 +0100 Subject: [PATCH] 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. --- repos/base/src/lib/ldso/main.cc | 34 +++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/repos/base/src/lib/ldso/main.cc b/repos/base/src/lib/ldso/main.cc index 416cf135b..f2876f89b 100644 --- a/repos/base/src/lib/ldso/main.cc +++ b/repos/base/src/lib/ldso/main.cc @@ -363,6 +363,7 @@ struct Linker::Elf_object : Object, Genode::List::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::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::Element, */ struct Init : Genode::List { + bool in_progress = false; + bool restart = false; + static Init *list() { static Init _list; @@ -619,10 +629,25 @@ struct Init : Genode::List 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 obj->dynamic.init_function(); } - Elf_object *next = obj->init_next(); - remove(obj); - obj = next; + obj = restart ? first() : next; + restart = false; } + + in_progress = false; } };