summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Bertalan <dani@danielbertalan.dev>2022-03-13 09:13:50 +0100
committerAndreas Kling <kling@serenityos.org>2022-05-01 12:42:01 +0200
commit7aca4089935d5ca8256b74e27c2abf1fb6dbdebc (patch)
treebdc0546ff6e17cffccdae1804046cce7507e4415
parent08c459e495608b4be6b9a032cc62ca65f4cef975 (diff)
downloadserenity-7aca4089935d5ca8256b74e27c2abf1fb6dbdebc.zip
LibELF: Fail gracefully when IFUNC resolver's object has textrels
.text sections of objects that contain textrels have to be writable during the relocation procedure. Because of this, we would segfault if we tried to execute IFUNC resolvers defined in them. Let's print a meaningful error message instead. Additionally, a warning is now printed when we load objects with textrels, as in the future, additional security mitigations might interfere with them being loaded.
-rw-r--r--Userland/Libraries/LibELF/DynamicLoader.cpp14
1 files changed, 13 insertions, 1 deletions
diff --git a/Userland/Libraries/LibELF/DynamicLoader.cpp b/Userland/Libraries/LibELF/DynamicLoader.cpp
index c57e5b2ed9..120d52f6ab 100644
--- a/Userland/Libraries/LibELF/DynamicLoader.cpp
+++ b/Userland/Libraries/LibELF/DynamicLoader.cpp
@@ -162,6 +162,7 @@ bool DynamicLoader::load_stage_2(unsigned flags)
VERIFY(flags & RTLD_GLOBAL);
if (m_dynamic_object->has_text_relocations()) {
+ dbgln("\033[33mWarning:\033[0m Dynamic object {} has text relocations", m_dynamic_object->filename());
for (auto& text_segment : m_text_segments) {
VERIFY(text_segment.address().get() != 0);
@@ -488,8 +489,13 @@ DynamicLoader::RelocationResult DynamicLoader::do_relocation(const ELF::DynamicO
symbol_location = VirtualAddress { (FlatPtr)0 };
} else {
symbol_location = res.value().address;
- if (res.value().type == STT_GNU_IFUNC)
+ if (res.value().type == STT_GNU_IFUNC) {
+ if (res.value().dynamic_object != nullptr && res.value().dynamic_object->has_text_relocations()) {
+ dbgln("\033[31mError:\033[0m Refusing to call IFUNC resolver defined in an object with text relocations.");
+ return RelocationResult::Failed;
+ }
symbol_location = call_ifunc_resolver(symbol_location);
+ }
}
VERIFY(symbol_location != m_dynamic_object->base_address());
*patch_ptr = symbol_location.get();
@@ -562,6 +568,12 @@ DynamicLoader::RelocationResult DynamicLoader::do_relocation(const ELF::DynamicO
resolver = m_dynamic_object->base_address().offset(relocation.addend());
else
resolver = m_dynamic_object->base_address().offset(*patch_ptr);
+
+ if (m_dynamic_object->has_text_relocations()) {
+ dbgln("\033[31mError:\033[0m Refusing to call IFUNC resolver defined in an object with text relocations.");
+ return RelocationResult::Failed;
+ }
+
*patch_ptr = call_ifunc_resolver(resolver).get();
break;
}