-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
DynamicLoader+Userland: Enable RELRO for shared libraries as well :^)
To support this, I had to reorganize the "load_elf" function into two passes. First we map all the dynamic objects, to get their symbols into the global lookup table. Then we link all the dynamic objects. So many read-only GOT's! :^)
- Loading branch information
1 parent
fa4c249
commit 713b3b3
Showing
2 changed files
with
28 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
/* | ||
* Copyright (c) 2020, Itamar S. <[email protected]> | ||
* Copyright (c) 2021, Andreas Kling <[email protected]> | ||
* Copyright (c) 2021, the SerenityOS developers. | ||
* All rights reserved. | ||
* | ||
|
@@ -50,7 +51,6 @@ namespace ELF { | |
|
||
namespace { | ||
HashMap<String, NonnullRefPtr<ELF::DynamicLoader>> g_loaders; | ||
HashMap<String, NonnullRefPtr<ELF::DynamicObject>> g_loaded_objects; | ||
Vector<NonnullRefPtr<ELF::DynamicObject>> g_global_objects; | ||
|
||
using MainFunction = int (*)(int, char**, char**); | ||
|
@@ -178,29 +178,37 @@ static void initialize_libc(DynamicObject& libc) | |
((libc_init_func*)res.value().address)(); | ||
} | ||
|
||
static void load_elf(const String& name) | ||
template<typename Callback> | ||
static void for_each_dependency_of_impl(const String& name, HashTable<String>& seen_names, Callback callback) | ||
{ | ||
dbgln_if(DYNAMIC_LOAD_DEBUG, "load_elf: {}", name); | ||
auto loader = g_loaders.get(name).value(); | ||
if (seen_names.contains(name)) | ||
return; | ||
seen_names.set(name); | ||
|
||
auto dynamic_object = loader->map(); | ||
ASSERT(dynamic_object); | ||
|
||
for (const auto& needed_name : get_dependencies(name)) { | ||
dbgln_if(DYNAMIC_LOAD_DEBUG, "needed library: {}", needed_name); | ||
String library_name = get_library_name(needed_name); | ||
if (!g_loaded_objects.contains(library_name)) { | ||
load_elf(library_name); | ||
} | ||
} | ||
for (const auto& needed_name : get_dependencies(name)) | ||
for_each_dependency_of_impl(get_library_name(needed_name), seen_names, callback); | ||
|
||
bool success = loader->link(RTLD_GLOBAL | RTLD_LAZY, g_total_tls_size); | ||
ASSERT(success); | ||
callback(*g_loaders.get(name).value()); | ||
} | ||
|
||
g_loaded_objects.set(name, *dynamic_object); | ||
g_global_objects.append(*dynamic_object); | ||
template<typename Callback> | ||
static void for_each_dependency_of(const String& name, Callback callback) | ||
{ | ||
HashTable<String> seen_names; | ||
for_each_dependency_of_impl(name, seen_names, move(callback)); | ||
} | ||
|
||
dbgln_if(DYNAMIC_LOAD_DEBUG, "load_elf: done {}", name); | ||
static void load_elf(const String& name) | ||
{ | ||
for_each_dependency_of(name, [](auto& loader) { | ||
auto dynamic_object = loader.map(); | ||
ASSERT(dynamic_object); | ||
g_global_objects.append(*dynamic_object); | ||
}); | ||
for_each_dependency_of(name, [](auto& loader) { | ||
bool success = loader.link(RTLD_GLOBAL | RTLD_LAZY, g_total_tls_size); | ||
ASSERT(success); | ||
}); | ||
} | ||
|
||
static NonnullRefPtr<DynamicLoader> commit_elf(const String& name) | ||
|