diff --git a/overlay/default.nix b/overlay/default.nix index e6403a8..98adaa5 100644 --- a/overlay/default.nix +++ b/overlay/default.nix @@ -86,7 +86,8 @@ in nullPkgs // { erisPatchHook = final.callPackage ./eris-patch-hook { patchelf = prev.patchelf.overrideAttrs (attrs: { - patches = attrs.patched or [ ] ++ [ ./patchelf/dynstr.patch ]; + patches = attrs.patched or [ ] + ++ [ ./patchelf/dynstr.patch ./patchelf/shiftFile.patch ]; }); }; diff --git a/overlay/patchelf/dynstr.patch b/overlay/patchelf/dynstr.patch index 0451d79..9d7a9f5 100644 --- a/overlay/patchelf/dynstr.patch +++ b/overlay/patchelf/dynstr.patch @@ -1,17 +1,19 @@ -From c66ec32bbdb88b0b4be0203c539bc6e91b471554 Mon Sep 17 00:00:00 2001 +From da00bd779e6f725eac6a01c0d3af6c1ba9543eda Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Fri, 19 Feb 2021 14:52:25 +0100 Subject: [PATCH] Expand LOAD segment to cover new .dynstr and .dynsym sections +This is not a robust fix, the first PT_LOAD segment is expanded +forward to cover .dynstr or .dynsym. --- - src/patchelf.cc | 40 ++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 40 insertions(+) + src/patchelf.cc | 44 ++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 44 insertions(+) diff --git a/src/patchelf.cc b/src/patchelf.cc -index 50eb13a..f13f460 100644 +index 50eb13a..1d5ecf3 100644 --- a/src/patchelf.cc +++ b/src/patchelf.cc -@@ -760,6 +760,46 @@ void ElfFile::writeReplacedSections(Elf_Off & curOff, +@@ -760,6 +760,50 @@ void ElfFile::writeReplacedSections(Elf_Off & curOff, curOff += roundUp(i.second.size(), sectionAlignment); } @@ -39,8 +41,12 @@ index 50eb13a..f13f460 100644 + debug("'%s' was moved out of a load segment…\n", sectionName.c_str()); + for (auto & phdr : phdrs) { + if (rdi(phdr.p_type) == PT_LOAD) { -+ if (rdi(shdr.sh_offset) < rdi(phdr.p_offset)) { -+ Elf64_Xword gap = rdi(phdr.p_offset) - rdi(shdr.sh_offset); ++ auto sh_offset = rdi(shdr.sh_offset); ++ auto p_offset = rdi(phdr.p_offset); ++ if (sh_offset < p_offset) { ++ Elf64_Xword gap ++ = (p_offset - sh_offset) ++ + ((getPageSize()-1) & sh_offset); + debug("grow PT_LOAD segment by 0x%x to cover '%s'\n", + gap, sectionName.c_str()); + wri(phdr.p_filesz, rdi(phdr.p_filesz) + gap); diff --git a/overlay/patchelf/shiftFile.patch b/overlay/patchelf/shiftFile.patch new file mode 100644 index 0000000..e379180 --- /dev/null +++ b/overlay/patchelf/shiftFile.patch @@ -0,0 +1,56 @@ +From 167aba8e9cc5b7850df59731fc02de08608fc6a6 Mon Sep 17 00:00:00 2001 +From: Emery Hemingway +Date: Thu, 11 Mar 2021 15:23:34 +0100 +Subject: [PATCH] Set exact size of new load segment in executables + +This fixes a bug where the length of new load segments did not +account for the offset of the segment within the load region. +--- + src/patchelf.cc | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/src/patchelf.cc b/src/patchelf.cc +index 287fea8..0c672e1 100644 +--- a/src/patchelf.cc ++++ b/src/patchelf.cc +@@ -581,18 +581,6 @@ void ElfFile::shiftFile(unsigned int extraPages, Elf_Addr sta + wri(phdrs[i].p_align, getPageSize()); + } + } +- +- /* Add a segment that maps the new program/section headers and +- PT_INTERP segment into memory. Otherwise glibc will choke. */ +- phdrs.resize(rdi(hdr->e_phnum) + 1); +- wri(hdr->e_phnum, rdi(hdr->e_phnum) + 1); +- Elf_Phdr & phdr = phdrs[rdi(hdr->e_phnum) - 1]; +- wri(phdr.p_type, PT_LOAD); +- wri(phdr.p_offset, 0); +- wri(phdr.p_vaddr, wri(phdr.p_paddr, startPage)); +- wri(phdr.p_filesz, wri(phdr.p_memsz, shift)); +- wri(phdr.p_flags, PF_R | PF_W); +- wri(phdr.p_align, getPageSize()); + } + + +@@ -957,6 +945,18 @@ void ElfFile::rewriteSectionsExecutable() + startOffset += neededPages * getPageSize(); + + shiftFile(neededPages, firstPage); ++ ++ /* Add a segment that maps the new program/section headers and ++ PT_INTERP segment into memory. Otherwise glibc will choke. */ ++ phdrs.resize(rdi(hdr->e_phnum) + 1); ++ wri(hdr->e_phnum, rdi(hdr->e_phnum) + 1); ++ Elf_Phdr & phdr = phdrs[rdi(hdr->e_phnum) - 1]; ++ wri(phdr.p_type, PT_LOAD); ++ wri(phdr.p_offset, 0); ++ wri(phdr.p_vaddr, wri(phdr.p_paddr, firstPage)); ++ wri(phdr.p_filesz, wri(phdr.p_memsz, neededSpace)); ++ wri(phdr.p_flags, PF_R | PF_W); // Can this be read-only? ++ wri(phdr.p_align, getPageSize()); + } + + +-- +2.29.2 +