From b8b64cb4f7e8bd75b17d8a73ec948fb0668be126 Mon Sep 17 00:00:00 2001 From: Markus Wichmann Date: Thu, 10 Sep 2026 16:09:21 +0200 Subject: [PATCH] Add relro support for static linking. In static PIE it is sensible to have a relro section, and so far no relro protections were applied in this case. For parity with dynamic linking, I am adding an explicit crash if relro protection fails, for the same conditions the dynlinker would fail. The syscall is inlined here, because TLS is not yet set up, and therefore syscall functions are not yet available. --- crt/rcrt1.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/crt/rcrt1.c b/crt/rcrt1.c index 901dff68..0ed06637 100644 --- a/crt/rcrt1.c +++ b/crt/rcrt1.c @@ -1,14 +1,63 @@ +#define SYSCALL_NO_TLS 1 +#include +#include +#include +#include "atomic.h" +#include "syscall.h" + #define START "_start" #define _dlstart_c _start_c #include "../ldso/dlstart.c" +#if ULONG_MAX == 0xffffffff +typedef Elf32_Phdr Phdr; +#else +typedef Elf64_Phdr Phdr; +#endif + int main(); weak void _init(); weak void _fini(); int __libc_start_main(int (*)(), int, char **, void (*)(), void(*)(), void(*)()); +extern const size_t _DYNAMIC[]; + +#ifdef __GNUC__ +__attribute__((__noinline__)) +#endif +void __apply_relro(size_t *sp) +{ + size_t *auxv = sp + *sp + 2; + while (*auxv++); + size_t pagesz = 0; + Phdr *ph; + size_t phnum, phent; + for (; *auxv; auxv += 2) { + switch (auxv[0]) { + case AT_PAGESZ: pagesz = auxv[1]; break; + case AT_PHDR: ph = (void *)auxv[1]; break; + case AT_PHNUM: phnum = auxv[1]; break; + case AT_PHENT: phent = auxv[1]; break; + } + } + Phdr *phdyn = 0, *phrelro = 0; + for (; (!phdyn || !phrelro) && phnum > 0; phnum--, ph = (void *)((char *)ph + phent)) { + if (ph->p_type == PT_DYNAMIC) phdyn = ph; + else if (ph->p_type == PT_GNU_RELRO) phrelro = ph; + } + if (phrelro) { + char *base = (char *)_DYNAMIC - phdyn->p_vaddr; + char *start = base + phrelro->p_vaddr; + char *end = start + phrelro->p_memsz; + start -= (uintptr_t)start & (pagesz - 1); + end += -(uintptr_t)end & (pagesz - 1); + long ret = __syscall(SYS_mprotect, start, end - start, PROT_READ); + if (ret != 0 && ret != -ENOSYS) a_crash(); + } +} hidden void __dls2(unsigned char *base, size_t *sp) { + __apply_relro(sp); __libc_start_main(main, *sp, (void *)(sp+1), _init, _fini, 0); } -- 2.54.0