Skip to content

issue with null sections #619

@ohnekopf

Description

@ohnekopf

the bug

assertion at the bottom of rewriteSectionsLibrary tripped when theres a null section at position 1 on the sht.

patchelf: patchelf.cc:961: void ElfFile<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Addr, Elf_Off, Elf_Dyn, Elf_Sym, Elf_Versym, Elf_Verdef, Elf_Verdaux, Elf_Verneed, Elf_Vernaux, Elf_Rel, Elf_Rela, ElfClass>::rewriteSectionsLibrary() [with Elf_Ehdr = Elf64_Ehdr; Elf_Phdr = Elf64_Phdr; Elf_Shdr = Elf64_Shdr; Elf_Addr = long unsigned int; Elf_Off = long unsigned int; Elf_Dyn = Elf64_Dyn; Elf_Sym = Elf64_Sym; Elf_Versym = short unsigned int; Elf_Verdef = Elf64_Verdef; Elf_Verdaux = Elf64_Verdaux; Elf_Verneed = Elf64_Verneed; Elf_Vernaux = Elf64_Vernaux; Elf_Rel = Elf64_Rel; Elf_Rela = Elf64_Rela; unsigned int ElfClass = 64]: Assertion `curOff == startOffset + neededSpace' failed.
Aborted

Steps To Reproduce

  1. take an elf executable (but with ET_DYN, havent tried other cases) that has a SHT_NULL entry (apart from the mandatory one at the top of the sht). i created one by appending 64 null bytes to a random gcc executable, because the section header table was at the end i could just add 1 to the counter on the elf header to get one.

  2. run patchelf --add-needed libX.so.Y on it, at least twice. the first time wont trip the assert if the null entry is not at position 1.

Expected behavior

no errors

patchelf --version output

current git master, also patchelf 0.18.0 from debian repo

running the program under a debugger shows that the problem comes from calls to replaceSection with a null section as the target, i dont understand quite well how that ends messing up the offset calculation, but adding a guard against it seems to help. also, using the --no-sort option prevents this.

this is my workaround, but im not sure if it makes sense, also its possible some non SHT_NULL sections might have an empty name?

diff --git a/src/patchelf.cc b/src/patchelf.cc
index 73f1b8d..693ac51 100644
--- a/src/patchelf.cc
+++ b/src/patchelf.cc
@@ -866,7 +866,7 @@ void ElfFile<ElfFileParamNames>::rewriteSectionsLibrary()
             const auto & sectionName = getSectionName(shdrs.at(i));
             const auto sectionSize = rdi(shdrs.at(i).sh_size);
 
-            if (!hasReplacedSection(sectionName)) {
+            if (sectionName != "" && !hasReplacedSection(sectionName) ) {
                 replaceSection(sectionName, sectionSize);
             }
 
@@ -1015,7 +1015,7 @@ void ElfFile<ElfFileParamNames>::rewriteSectionsExecutable()
             lastReplaced = i - 1;
             break;
         }
-        if (!replacedSections.count(sectionName)) {
+        if (sectionName != "" && !replacedSections.count(sectionName)) {
             debug("replacing section '%s' which is in the way\n", sectionName.c_str());
             replaceSection(sectionName, rdi(shdr.sh_size));
         }

another workaround is striping the executable which removes all null sections

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions