patchelf: add 3 fixes to optimize and fix uninative

* uninative-3.10 and 4.0 doesn't work on e.g. ubuntu-18.04, because patchelf-uninative
  makes the binaries unusable and e.g. mkfs.ext4 segfaults in loader, see:
  https://github.com/NixOS/patchelf/issues/492

* mke2fs.real, mkfs.ext2.real, mkfs.ext3.real, mkfs.ext4.real are indentical
  binary with multiple hardlinks and we end calling patchelf-uninative 4
  times even when the interpreter is already set correctly from the build

  The issue was reported upstream with mkfs.ext4.real as possible reproducer:
  https://github.com/NixOS/patchelf/issues/492#issuecomment-1602862272

  To fix uninative we need to first release new uninative tarball and
  then upgrade it in master, mickledore, kirkstone, dunfell

* originally reported in:
  https://lists.openembedded.org/g/openembedded-core/message/182862
  with temporary work around (applicable locally without waiting for
  new uninative release):
  https://lists.openembedded.org/g/openembedded-core/message/183314

(From OE-Core rev: f0499b58d1dd149300a349dde8f6664679df13e6)

Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Martin Jansa 2023-07-31 21:10:05 +02:00 committed by Richard Purdie
parent 5797574236
commit d505ab5ea5
4 changed files with 110 additions and 1 deletions

View File

@ -0,0 +1,31 @@
From f5df94952e87eaa390e5c845bc48fdb3dbc31cc2 Mon Sep 17 00:00:00 2001
From: Yuta Hayama <hayama@lineo.co.jp>
Date: Fri, 21 Jul 2023 10:47:02 +0900
Subject: [PATCH] Set interpreter only when necessary
If the given interpreter is already set, nothing needs to be done.
As with modifySoname(), it skips unnecessary processing.
Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com>
---
Upstream-Status: Submitted [https://github.com/NixOS/patchelf/pull/508]
src/patchelf.cc | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/patchelf.cc b/src/patchelf.cc
index 86429c4..e562c49 100644
--- a/src/patchelf.cc
+++ b/src/patchelf.cc
@@ -1460,6 +1460,11 @@ void ElfFile<ElfFileParamNames>::modifySoname(sonameMode op, const std::string &
template<ElfFileParams>
void ElfFile<ElfFileParamNames>::setInterpreter(const std::string & newInterpreter)
{
+ if (getInterpreter() == newInterpreter) {
+ debug("given interpreter is already set\n");
+ return;
+ }
+
std::string & section = replaceSection(".interp", newInterpreter.size() + 1);
setSubstr(section, 0, newInterpreter + '\0');
changed = true;

View File

@ -0,0 +1,42 @@
From 1198329b922f3cdddc3e87a7c81d7730b646c088 Mon Sep 17 00:00:00 2001
From: Yuta Hayama <hayama@lineo.co.jp>
Date: Fri, 28 Jul 2023 16:22:31 +0900
Subject: [PATCH] align startOffset with p_align instead of pagesize for
compatibility
According to the ELF specification, the alignment of loadable process segments
should satisfy (p_vaddr mod pagesize) == (p_offset mod pagesize). However,
glibc earlier than 2.35 incorrectly requires that the LOAD segment be (p_vaddr
mod p_align) == (p_offset mod p_align), and will output the error message
"ELF load command address/offset not properly aligned" if this is not met.
Since there are many systems that use glibc earlier than 2.35, it is preferable
that newly added LOAD segments satisfy (p_vaddr mod p_align) == (p_offset mod
p_align) for compatibility.
Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com>
---
Upstream-Status: Submitted [https://github.com/NixOS/patchelf/pull/510]
src/patchelf.cc | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/patchelf.cc b/src/patchelf.cc
index 82b4b46..6edb81a 100644
--- a/src/patchelf.cc
+++ b/src/patchelf.cc
@@ -843,7 +843,13 @@ void ElfFile<ElfFileParamNames>::rewriteSectionsLibrary()
neededSpace += headerTableSpace;
debug("needed space is %d\n", neededSpace);
- Elf_Off startOffset = roundUp(fileContents->size(), getPageSize());
+ /* glibc earlier than 2.35 requires that the LOAD segment satisfies
+ (p_vaddr mod p_align) == (p_offset mod p_align).
+ The ELF specification requires that loadable process segments satisfy
+ (p_vaddr mod pagesize) == (p_offset mod pagesize), so glibc is probably
+ wrong, but here startOffset is calculated according to p_align for
+ compatibility. */
+ Elf_Off startOffset = roundUp(fileContents->size(), alignStartPage);
// In older version of binutils (2.30), readelf would check if the dynamic
// section segment is strictly smaller than the file (and not same size).

View File

@ -0,0 +1,32 @@
From 299ad5766921d593e11a42a8e4dec55b4b350876 Mon Sep 17 00:00:00 2001
From: Yuta Hayama <hayama@lineo.co.jp>
Date: Mon, 31 Jul 2023 11:58:49 +0900
Subject: [PATCH] make LOAD segment extensions based on p_align instead of
pagesize
Since the p_align of the LOAD segment is no longer pagesize, the actual p_align
value is used to calculate for the LOAD segment extension.
If calculated with pagesize, new LOAD segment may be added even though the
existing LOAD segment can be extended.
Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com>
---
Upstream-Status: Submitted [https://github.com/NixOS/patchelf/pull/510]
src/patchelf.cc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/patchelf.cc b/src/patchelf.cc
index 6edb81a..86429c4 100644
--- a/src/patchelf.cc
+++ b/src/patchelf.cc
@@ -885,7 +885,7 @@ void ElfFile<ElfFileParamNames>::rewriteSectionsLibrary()
rdi(lastSeg.p_type) == PT_LOAD &&
rdi(lastSeg.p_flags) == (PF_R | PF_W) &&
rdi(lastSeg.p_align) == alignStartPage) {
- auto segEnd = roundUp(rdi(lastSeg.p_offset) + rdi(lastSeg.p_memsz), getPageSize());
+ auto segEnd = roundUp(rdi(lastSeg.p_offset) + rdi(lastSeg.p_memsz), alignStartPage);
if (segEnd == startOffset) {
auto newSz = startOffset + neededSpace - rdi(lastSeg.p_offset);
wri(lastSeg.p_filesz, wri(lastSeg.p_memsz, newSz));

View File

@ -4,7 +4,11 @@ HOMEPAGE = "https://github.com/NixOS/patchelf"
LICENSE = "GPL-3.0-only"
SRC_URI = "git://github.com/NixOS/patchelf;protocol=https;branch=master"
SRC_URI = "git://github.com/NixOS/patchelf;protocol=https;branch=master \
file://0001-Set-interpreter-only-when-necessary.patch \
file://0002-align-startOffset-with-p_align-instead-of-pagesize-f.patch \
file://0003-make-LOAD-segment-extensions-based-on-p_align-instea.patch \
"
SRCREV = "99c24238981b7b1084313aca8f5c493bb46f302c"
S = "${WORKDIR}/git"