Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 58 additions & 7 deletions options/rtld/generic/linker.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "mlibc/internal-sysdeps.hpp"
Comment thread
oberrow marked this conversation as resolved.
Outdated
#include <mlibc/arch-defs.hpp>
#include <stdint.h>
#include <string.h>
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Comment thread
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;
Expand Down Expand Up @@ -896,6 +906,19 @@ void ObjectRepository::_parseDynamic(SharedObject *object) {
object->soName = reinterpret_cast<const char *>(object->baseAddress
+ object->stringTableOffset + *soname_offset);
}
if (object->haveTextRel)
Comment thread
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;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The 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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be done in linkObjects() to be symmetrical with the code path that removes PROT_WRITE again.

}

void ObjectRepository::_parseVerdef(SharedObject *object) {
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions options/rtld/generic/linker.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ struct SharedObject {
bool symbolicResolution;
bool eagerBinding;
bool haveStaticTls;
bool haveTextRel;

// vector of dependencies
frg::vector<SharedObject *, MemoryAllocator> dependencies;
Expand All @@ -248,6 +249,8 @@ struct SharedObject {
size_t phdrEntrySize = 0;
size_t phdrCount = 0;

frg::vector<void*, MemoryAllocator> exec_phdrs;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have phdrPointer etc. which can be used to iterate over the PHDRs.


frg::tuple<ObjectSymbol, SymbolVersion> getSymbolByIndex(size_t index);
};

Expand Down
1 change: 1 addition & 0 deletions options/rtld/loongarch64/elf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ using elf_vernaux = Elf64_Vernaux;
#define R_ABSOLUTE R_LARCH_64
#define R_GLOB_DAT R_LARCH_64
#define R_RELATIVE R_LARCH_RELATIVE
#define R_PC32 R_LARCH_PC32
#define R_IRELATIVE R_LARCH_IRELATIVE
#define R_COPY R_LARCH_COPY
#define R_TLS_DTPMOD R_LARCH_TLS_DTPMOD64
Expand Down
1 change: 1 addition & 0 deletions options/rtld/m68k/elf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ using elf_vernaux = Elf32_Vernaux;
#define R_ABSOLUTE R_68K_32
#define R_GLOB_DAT R_68K_GLOB_DAT
#define R_RELATIVE R_68K_RELATIVE
#define R_PC32 R_68K_PC32
#define R_OFFSET R_68K_PC32
#define R_COPY R_68K_COPY
#define R_TLS_DTPMOD R_68K_TLS_DTPMOD32
Expand Down
1 change: 1 addition & 0 deletions options/rtld/riscv64/elf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ using elf_vernaux = Elf64_Vernaux;
#define R_ABSOLUTE R_RISCV_64
#define R_GLOB_DAT R_RISCV_64
#define R_RELATIVE R_RISCV_RELATIVE
#define R_PC32 R_RISCV_PC32
#define R_IRELATIVE R_RISCV_IRELATIVE
// #define R_OFFSET
#define R_COPY R_RISCV_COPY
Expand Down
1 change: 1 addition & 0 deletions options/rtld/x86/elf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ using elf_vernaux = Elf32_Vernaux;
#define R_ABSOLUTE R_386_32
#define R_GLOB_DAT R_386_GLOB_DAT
#define R_RELATIVE R_386_RELATIVE
#define R_PC32 R_386_PC32
#define R_IRELATIVE R_386_IRELATIVE
#define R_OFFSET R_386_PC32
#define R_COPY R_386_COPY
Expand Down
1 change: 1 addition & 0 deletions options/rtld/x86_64/elf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ using elf_vernaux = Elf64_Vernaux;
#define R_NONE R_X86_64_NONE
#define R_JUMP_SLOT R_X86_64_JUMP_SLOT
#define R_ABSOLUTE R_X86_64_64
#define R_PC32 R_X86_64_PC32
#define R_GLOB_DAT R_X86_64_GLOB_DAT
#define R_RELATIVE R_X86_64_RELATIVE
#define R_IRELATIVE R_X86_64_IRELATIVE
Expand Down
2 changes: 1 addition & 1 deletion sysdeps/linux/m68k/crt-src/Scrt1.S
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ _start:
suba.l %fp, %fp
move.l %sp, %d0
lea _GLOBAL_OFFSET_TABLE_@GOTPC (%pc), %a5
move.l main@GOT(%a5), -(%sp)
move.l %d0, -(%sp)
move.l main@GOT(%a5), -(%sp)
jbsr __mlibc_entry@PLTPC

.section .note.GNU-stack,"",%progbits
Loading