From 9f1c0af97b947687d3f916e10baa405b11d57584 Mon Sep 17 00:00:00 2001 From: Breno Rodrigues Guimaraes Date: Tue, 7 Mar 2023 18:46:25 -0300 Subject: [PATCH] Set the alignment of the new LOAD segment the same as others --- .github/workflows/publish.yml | 2 +- src/patchelf.cc | 11 ++++++++--- tests/Makefile.am | 5 ++++- tests/set-rpath-library.sh | 10 ++++++++++ 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 0e600c35..c7ed3372 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -89,7 +89,7 @@ jobs: rm -f dist/* cd patchelf-* ./configure --prefix /patchelf - make check + make check || (cat tests/test-suite.log; exit 1) make install-strip cd - tar -czf ./dist/patchelf-\$(cat patchelf-*/version)-\$(uname -m).tar.gz -C /patchelf . diff --git a/src/patchelf.cc b/src/patchelf.cc index d814d3fd..62af389f 100644 --- a/src/patchelf.cc +++ b/src/patchelf.cc @@ -800,12 +800,17 @@ void ElfFile::rewriteSectionsLibrary() page of other segments. */ Elf_Addr startPage = 0; Elf_Addr firstPage = 0; + unsigned alignStartPage = getPageSize(); for (auto & phdr : phdrs) { - Elf_Addr thisPage = roundUp(rdi(phdr.p_vaddr) + rdi(phdr.p_memsz), getPageSize()); + Elf_Addr thisPage = rdi(phdr.p_vaddr) + rdi(phdr.p_memsz); if (thisPage > startPage) startPage = thisPage; if (rdi(phdr.p_type) == PT_PHDR) firstPage = rdi(phdr.p_vaddr) - rdi(phdr.p_offset); + unsigned thisAlign = rdi(phdr.p_align); + alignStartPage = std::max(alignStartPage, thisAlign); } + startPage = roundUp(startPage, alignStartPage); + debug("last page is 0x%llx\n", (unsigned long long) startPage); debug("first page is 0x%llx\n", (unsigned long long) firstPage); @@ -873,7 +878,7 @@ void ElfFile::rewriteSectionsLibrary() if (!phdrs.empty() && rdi(lastSeg.p_type) == PT_LOAD && rdi(lastSeg.p_flags) == (PF_R | PF_W) && - rdi(lastSeg.p_align) == getPageSize()) { + rdi(lastSeg.p_align) == alignStartPage) { auto segEnd = roundUp(rdi(lastSeg.p_offset) + rdi(lastSeg.p_memsz), getPageSize()); if (segEnd == startOffset) { auto newSz = startOffset + neededSpace - rdi(lastSeg.p_offset); @@ -892,7 +897,7 @@ void ElfFile::rewriteSectionsLibrary() wri(phdr.p_vaddr, wri(phdr.p_paddr, startPage)); wri(phdr.p_filesz, wri(phdr.p_memsz, neededSpace)); wri(phdr.p_flags, PF_R | PF_W); - wri(phdr.p_align, getPageSize()); + wri(phdr.p_align, alignStartPage); } normalizeNoteSegments(); diff --git a/tests/Makefile.am b/tests/Makefile.am index 55a8f756..4ae540ae 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -119,7 +119,7 @@ check_DATA = libbig-dynstr.debug # - with libtool, it is difficult to control options # - with libtool, it is not possible to compile convenience *dynamic* libraries :-( check_PROGRAMS += libfoo.so libfoo-scoped.so libbar.so libbar-scoped.so libsimple.so libsimple-execstack.so libbuildid.so libtoomanystrtab.so \ - phdr-corruption.so many-syms-main libmany-syms.so + phdr-corruption.so many-syms-main libmany-syms.so liboveralign.so libbuildid_so_SOURCES = simple.c libbuildid_so_LDFLAGS = $(LDFLAGS_sharedlib) -Wl,--build-id @@ -143,6 +143,9 @@ libbar_scoped_so_LDFLAGS = $(LDFLAGS_sharedlib) libsimple_so_SOURCES = simple.c libsimple_so_LDFLAGS = $(LDFLAGS_sharedlib) -Wl,-z,noexecstack +liboveralign_so_SOURCES = simple.c +liboveralign_so_LDFLAGS = $(LDFLAGS_sharedlib) -Wl,-z,max-page-size=0x10000 + libsimple_execstack_so_SOURCES = simple.c libsimple_execstack_so_LDFLAGS = $(LDFLAGS_sharedlib) -Wl,-z,execstack diff --git a/tests/set-rpath-library.sh b/tests/set-rpath-library.sh index 55661a13..55a4c168 100755 --- a/tests/set-rpath-library.sh +++ b/tests/set-rpath-library.sh @@ -14,6 +14,7 @@ mkdir -p "${SCRATCH}/libsB" cp main-scoped "${SCRATCH}/" cp libfoo-scoped.so "${SCRATCH}/libsA/" cp libbar-scoped.so "${SCRATCH}/libsB/" +cp liboveralign.so "${SCRATCH}/" oldRPath=$(../src/patchelf --print-rpath "${SCRATCH}"/main-scoped) if test -z "$oldRPath"; then oldRPath="/oops"; fi @@ -56,3 +57,12 @@ if test "$exitCode" != 46; then echo "bad exit code!" exit 1 fi + +# ALL loads should have the same alignment +lib="${SCRATCH}/liboveralign.so" +../src/patchelf --set-rpath "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "$lib" +num_alignments=$(${READELF} -W -l "${lib}" | grep LOAD | awk '{ print $NF }' | sort -u | wc -l) +echo "$num_alignments" +if test "${num_alignments}" -ne "1"; then + exit 1 +fi