diff options
author | Daniel Bertalan <dani@danielbertalan.dev> | 2022-03-13 09:13:50 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-05-01 12:42:01 +0200 |
commit | 7aca4089935d5ca8256b74e27c2abf1fb6dbdebc (patch) | |
tree | bdc0546ff6e17cffccdae1804046cce7507e4415 | |
parent | 08c459e495608b4be6b9a032cc62ca65f4cef975 (diff) | |
download | serenity-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.cpp | 14 |
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; } |