-
-
Notifications
You must be signed in to change notification settings - Fork 218
options/rtld: Implement relocations in text sections (DT/DF_TEXTREL) #1448
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
659d0d9
9312c3a
c239fc6
4ca7219
e01e4a2
8ee9303
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| #include "mlibc/internal-sysdeps.hpp" | ||
| #include <mlibc/arch-defs.hpp> | ||
| #include <stdint.h> | ||
| #include <string.h> | ||
|
|
@@ -501,6 +502,10 @@ void ObjectRepository::_fetchFromPhdrs(SharedObject *object, void *phdr_pointer, | |
| object->tlsImageSize = phdr->p_filesz; | ||
| tls_offset = phdr->p_vaddr; | ||
| break; | ||
| case PT_LOAD: | ||
| if (phdr->p_flags & PF_X) | ||
| object->exec_phdrs.push_back(phdr); | ||
| break; | ||
| case PT_INTERP: | ||
| object->interpreterPath = frg::string<MemoryAllocator>{ | ||
| (char*)(object->baseAddress + phdr->p_vaddr), | ||
|
|
@@ -626,8 +631,14 @@ frg::expected<LinkerError, void> ObjectRepository::_fetchFromFile(SharedObject * | |
| prot |= PROT_READ; | ||
| if(phdr->p_flags & PF_W) | ||
| prot |= PROT_WRITE; | ||
| if(phdr->p_flags & PF_X) | ||
| if(phdr->p_flags & PF_X){ | ||
| prot |= PROT_EXEC; | ||
| // possible use-after-free? | ||
| // if someone ever frees the phdr_buffer, then this is a use-after-free | ||
| // but currently we seem to leak it | ||
| // :) | ||
| object->exec_phdrs.push_back(phdr); | ||
| } | ||
|
|
||
| #if MLIBC_MAP_DSO_SEGMENTS | ||
| // we can avoid the vm_protect call if we don't have to write to the segment | ||
|
|
@@ -775,18 +786,17 @@ void ObjectRepository::_parseDynamic(SharedObject *object) { | |
| object->eagerBinding = true; | ||
|
|
||
| auto ignored = DF_BIND_NOW | DF_SYMBOLIC | DF_STATIC_TLS; | ||
| #ifdef __riscv | ||
| // Work around https://sourceware.org/bugzilla/show_bug.cgi?id=24673. | ||
| ignored |= DF_TEXTREL; | ||
|
oberrow marked this conversation as resolved.
Outdated
|
||
| #else | ||
| if(dynamic->d_un.d_val & DF_TEXTREL) | ||
| mlibc::panicLogger() << "\e[31mrtld: DF_TEXTREL is unimplemented" << frg::endlog; | ||
| #endif | ||
| object->haveTextRel = true; | ||
| if(dynamic->d_un.d_val & ~ignored) | ||
| mlibc::infoLogger() << "\e[31mrtld: DT_FLAGS(" << frg::hex_fmt{dynamic->d_un.d_val & ~ignored} | ||
| << ") is not implemented correctly!\e[39m" | ||
| << frg::endlog; | ||
| } break; | ||
| case DT_TEXTREL: | ||
| object->haveTextRel = true; | ||
| break; | ||
| case DT_FLAGS_1: | ||
| if(dynamic->d_un.d_val & DF_1_NOW) | ||
| object->eagerBinding = true; | ||
|
|
@@ -896,6 +906,19 @@ void ObjectRepository::_parseDynamic(SharedObject *object) { | |
| object->soName = reinterpret_cast<const char *>(object->baseAddress | ||
| + object->stringTableOffset + *soname_offset); | ||
| } | ||
| if (object->haveTextRel) | ||
|
oberrow marked this conversation as resolved.
Outdated
|
||
| { | ||
| for (auto &phdr_ptr : object->exec_phdrs) | ||
| { | ||
| elf_phdr* phdr = (elf_phdr*)phdr_ptr; | ||
| void* addr = (void*)(phdr->p_vaddr + (uintptr_t)object->baseAddress); | ||
| int prot = PROT_WRITE | PROT_READ | PROT_EXEC; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should never map as RWX. Instead, map as RW first and then change that to RX. |
||
| if (mlibc::sys_vm_protect) | ||
| mlibc::sys_vm_protect(addr, phdr->p_memsz, prot); | ||
| else | ||
| __ensure(!"sys_vm_protect required when DF_TEXTREL/DT_TEXTREL is present"); | ||
| } | ||
| } | ||
|
Comment on lines
+905
to
+915
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could be done in |
||
| } | ||
|
|
||
| void ObjectRepository::_parseVerdef(SharedObject *object) { | ||
|
|
@@ -1129,7 +1152,8 @@ SharedObject::SharedObject(const char *name, frg::string<MemoryAllocator> path, | |
| dependencies(getAllocator()), tlsModel(TlsModel::null), | ||
| tlsOffset(0), globalRts(0), wasLinked(false), | ||
| scheduledForInit(false), onInitStack(false), | ||
| wasInitialized(false) { } | ||
| wasInitialized(false), | ||
| exec_phdrs(getAllocator()) { } | ||
|
|
||
| SharedObject::SharedObject(const char *name, const char *path, | ||
| bool is_main_object, Scope *localScope, uint64_t object_rts) | ||
|
|
@@ -1787,6 +1811,25 @@ void Loader::linkObjects(SharedObject *root) { | |
| linkMap->next = &(object->linkMap); | ||
| object->inLinkMap = true; | ||
| } | ||
|
|
||
| for (auto object : _linkBfs) | ||
| { | ||
| // Remap exec phdrs as RX if the object has DF/DT_TEXTREL present | ||
| // in the dynamic header | ||
| if (object->haveTextRel) | ||
| { | ||
| for (auto &phdr_ptr : object->exec_phdrs) | ||
| { | ||
| elf_phdr* phdr = (elf_phdr*)phdr_ptr; | ||
| void* addr = (void*)(phdr->p_vaddr + (uintptr_t)object->baseAddress); | ||
| int prot = PROT_READ | PROT_EXEC; | ||
| if (mlibc::sys_vm_protect) | ||
| mlibc::sys_vm_protect(addr, phdr->p_memsz, prot); | ||
| else | ||
| __ensure(!"sys_vm_protect required when DF_TEXTREL/DT_TEXTREL is present"); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void Loader::_buildTlsMaps() { | ||
|
|
@@ -1973,6 +2016,14 @@ void Loader::_processRelocations(Relocation &rel) { | |
| } break; | ||
| #endif | ||
|
|
||
| case R_PC32: | ||
| { | ||
| __ensure(rel.symbol_index()); | ||
| uintptr_t symbol_addr = p ? p->virtualAddress() : 0; | ||
| rel.relocate(symbol_addr + rel.addend_norel() - (elf_addr)rel.destination()); | ||
| break; | ||
| } | ||
|
|
||
| case R_ABSOLUTE: { | ||
| __ensure(rel.symbol_index()); | ||
| uintptr_t symbol_addr = p ? p->virtualAddress() : 0; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -222,6 +222,7 @@ struct SharedObject { | |
| bool symbolicResolution; | ||
| bool eagerBinding; | ||
| bool haveStaticTls; | ||
| bool haveTextRel; | ||
|
|
||
| // vector of dependencies | ||
| frg::vector<SharedObject *, MemoryAllocator> dependencies; | ||
|
|
@@ -248,6 +249,8 @@ struct SharedObject { | |
| size_t phdrEntrySize = 0; | ||
| size_t phdrCount = 0; | ||
|
|
||
| frg::vector<void*, MemoryAllocator> exec_phdrs; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We already have |
||
|
|
||
| frg::tuple<ObjectSymbol, SymbolVersion> getSymbolByIndex(size_t index); | ||
| }; | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.