summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelipe Sateler <fsateler@debian.org>2021-08-24 20:16:12 -0400
committerFelipe Sateler <fsateler@debian.org>2021-08-24 20:16:12 -0400
commit3922f6b9908fb603207169b3f5fb4670da6c0d13 (patch)
treefd6017332d34c66156d9d654caae9bc0947db791
parent077975126dd8dd796113f7819f929181fdf9d921 (diff)
Update MIPS fix patch with what was merged upstream
It didnt make 0.13, but it will be there for 0.14
-rw-r--r--debian/patches/Adjust-DT_MIPS_RLD_MAP_REL-dynamic-section-entry-if-prese.patch110
-rw-r--r--debian/patches/Adjust-PT_MIPS_ABIFLAGS-segment-if-present.patch23
2 files changed, 103 insertions, 30 deletions
diff --git a/debian/patches/Adjust-DT_MIPS_RLD_MAP_REL-dynamic-section-entry-if-prese.patch b/debian/patches/Adjust-DT_MIPS_RLD_MAP_REL-dynamic-section-entry-if-prese.patch
index f63f702..b05fac1 100644
--- a/debian/patches/Adjust-DT_MIPS_RLD_MAP_REL-dynamic-section-entry-if-prese.patch
+++ b/debian/patches/Adjust-DT_MIPS_RLD_MAP_REL-dynamic-section-entry-if-prese.patch
@@ -8,7 +8,7 @@ RPATH added that way.
The problem was around the MIPS-specific mechanism of setting up the
debug map pointer. When DT_MIPS_RLD_MAP_REL entry in the dynamic section
-is not zero, it holds the relative address of __RLD_MAP -- an offset
+is present, it holds the relative address of __RLD_MAP -- an offset
relative to this dynamic section entry. Dynamic linker puts the
pointer to the `r_debug` structure there.
@@ -20,23 +20,31 @@ valid anymore and should be updated.
This commit adds the necessary update.
+In the corner case when DT_MIPS_RLD_MAP_REL is present, but
+.rld_map section is not, the dynamic loader writes the debug
+pointer to some arbitrary bytes in memory. To avoid crushes
+on otherwise "working" binaries, we set offset to zero
+so that the dynamic loader would just overwrite the dynamic
+section.
+
Here we also import DT_MIPS_RLD_MAP_REL definition in elf.h form
glibc commit a2057c984e4314c3740f04cf54e36c824e4c8f32.
Refs: #82
Signed-off-by: Ivan A. Melnikov <iv@altlinux.org>
-
-DT_MIPS_RLD_MAP_REL
---
- src/elf.h | 6 +++++-
- src/patchelf.cc | 12 ++++++++++--
- 2 files changed, 15 insertions(+), 3 deletions(-)
+ src/elf.h | 6 +++++-
+ src/patchelf.cc | 21 +++++++++++++++++++--
+ tests/Makefile.am | 1 +
+ tests/set-rpath-rel-map.sh | 37 +++++++++++++++++++++++++++++++++++++
+ 4 files changed, 62 insertions(+), 3 deletions(-)
+ create mode 100755 tests/set-rpath-rel-map.sh
diff --git a/src/elf.h b/src/elf.h
-index 87cb141..e4e167c 100644
+index 576990d..ae1524a 100644
--- a/src/elf.h
+++ b/src/elf.h
-@@ -1640,7 +1640,11 @@ typedef struct
+@@ -1642,7 +1642,11 @@ typedef struct
PLT is writable. For a non-writable PLT, this is omitted or has a zero
value. */
#define DT_MIPS_RWPLT 0x70000034
@@ -45,38 +53,102 @@ index 87cb141..e4e167c 100644
+ in a PIE as it stores a relative offset from the address of the tag
+ rather than an absolute address. */
+#define DT_MIPS_RLD_MAP_REL 0x70000035
-+#define DT_MIPS_NUM 0x36
++#define DT_MIPS_NUM 0x36
/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */
diff --git a/src/patchelf.cc b/src/patchelf.cc
-index 05ec793..18e1f83 100644
+index fd1e7b7..d713728 100644
--- a/src/patchelf.cc
+++ b/src/patchelf.cc
-@@ -1078,9 +1078,9 @@ void ElfFile<ElfFileParamNames>::rewriteHeaders(Elf_Addr phdrAddress)
+@@ -1089,9 +1089,9 @@ void ElfFile<ElfFileParamNames>::rewriteHeaders(Elf_Addr phdrAddress)
(e.g., those produced by klibc's klcc). */
auto shdrDynamic = findSection2(".dynamic");
if (shdrDynamic) {
-- Elf_Dyn * dyn = (Elf_Dyn *) (contents + rdi(shdrDynamic->sh_offset));
-+ Elf_Dyn * dyn_table = (Elf_Dyn *) (contents + rdi(shdrDynamic->sh_offset));
+- auto dyn = (Elf_Dyn *)(contents + rdi(shdrDynamic->sh_offset));
++ auto dyn_table = (Elf_Dyn *) (contents + rdi(shdrDynamic->sh_offset));
unsigned int d_tag;
- for ( ; (d_tag = rdi(dyn->d_tag)) != DT_NULL; dyn++)
-+ for (Elf_Dyn * dyn = dyn_table; (d_tag = rdi(dyn->d_tag)) != DT_NULL; dyn++)
++ for (auto dyn = dyn_table; (d_tag = rdi(dyn->d_tag)) != DT_NULL; dyn++)
if (d_tag == DT_STRTAB)
dyn->d_un.d_ptr = findSection(".dynstr").sh_addr;
else if (d_tag == DT_STRSZ)
-@@ -1119,6 +1119,14 @@ void ElfFile<ElfFileParamNames>::rewriteHeaders(Elf_Addr phdrAddress)
+@@ -1130,6 +1130,23 @@ void ElfFile<ElfFileParamNames>::rewriteHeaders(Elf_Addr phdrAddress)
dyn->d_un.d_ptr = findSection(".gnu.version_r").sh_addr;
else if (d_tag == DT_VERSYM)
dyn->d_un.d_ptr = findSection(".gnu.version").sh_addr;
+ else if (d_tag == DT_MIPS_RLD_MAP_REL) {
+ /* the MIPS_RLD_MAP_REL tag stores the offset to the debug
+ pointer, relative to the address of the tag */
-+ debug("Updating DT_MIPS_RLD_MAP_REL");
-+ Elf_Addr rtld_map_addr = findSection(".rld_map").sh_addr;
-+ auto dyn_offset = ((char*)dyn) - ((char*)dyn_table);
-+ dyn->d_un.d_ptr = rtld_map_addr + dyn_offset - shdrDynamic->sh_addr;
++ auto shdr = findSection2(".rld_map");
++ if (shdr) {
++ auto rld_map_addr = findSection(".rld_map").sh_addr;
++ auto dyn_offset = ((char*)dyn) - ((char*)dyn_table);
++ dyn->d_un.d_ptr = rld_map_addr + dyn_offset - shdrDynamic->sh_addr;
++ } else {
++ /* ELF file with DT_MIPS_RLD_MAP_REL but without .rld_map
++ is broken, and it's not our job to fix it; yet, we have
++ to find some location for dynamic loader to write the
++ debug pointer to; well, let's write it right here */
++ fprintf(stderr, "warning: DT_MIPS_RLD_MAP_REL entry is present, but .rld_map section is not\n");
++ dyn->d_un.d_ptr = 0;
++ }
+ }
}
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index f8176e0..3e6b356 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -22,6 +22,7 @@ src_TESTS = \
+ plain-fail.sh plain-run.sh shrink-rpath.sh set-interpreter-short.sh \
+ set-interpreter-long.sh set-rpath.sh add-rpath.sh no-rpath.sh big-dynstr.sh \
+ set-rpath-library.sh soname.sh shrink-rpath-with-allowed-prefixes.sh \
++ set-rpath-rel-map.sh \
+ force-rpath.sh \
+ plain-needed.sh \
+ output-flag.sh \
+diff --git a/tests/set-rpath-rel-map.sh b/tests/set-rpath-rel-map.sh
+new file mode 100755
+index 0000000..efc0943
+--- /dev/null
++++ b/tests/set-rpath-rel-map.sh
+@@ -0,0 +1,37 @@
++#! /bin/sh -e
++
++if ! objdump -p main | grep -q MIPS_RLD_MAP_REL; then
++ echo "No MIPS_RLD_MAP_REL dynamic section entry, skipping"
++ exit 0
++fi
++
++SCRATCH=scratch/$(basename $0 .sh)
++
++rm -rf ${SCRATCH}
++mkdir -p ${SCRATCH}
++mkdir -p ${SCRATCH}/libsA
++mkdir -p ${SCRATCH}/libsB
++
++cp main ${SCRATCH}/
++cp libfoo.so ${SCRATCH}/libsA/
++cp libbar.so ${SCRATCH}/libsB/
++
++# break the main executable by removing .rld_map section
++objcopy --remove-section .rld_map ${SCRATCH}/main
++
++oldRPath=$(../src/patchelf --print-rpath ${SCRATCH}/main)
++if test -z "$oldRPath"; then oldRPath="/oops"; fi
++../src/patchelf --force-rpath --set-rpath $oldRPath:$(pwd)/${SCRATCH}/libsA:$(pwd)/${SCRATCH}/libsB ${SCRATCH}/main
++
++if test "$(uname)" = FreeBSD; then
++ export LD_LIBRARY_PATH=$(pwd)/${SCRATCH}/libsB
++fi
++
++exitCode=0
++
++(cd ${SCRATCH} && ./main) || exitCode=$?
++
++if test "$exitCode" != 46; then
++ echo "bad exit code!"
++ exit 1
++fi
diff --git a/debian/patches/Adjust-PT_MIPS_ABIFLAGS-segment-if-present.patch b/debian/patches/Adjust-PT_MIPS_ABIFLAGS-segment-if-present.patch
index ed33108..dfd35fb 100644
--- a/debian/patches/Adjust-PT_MIPS_ABIFLAGS-segment-if-present.patch
+++ b/debian/patches/Adjust-PT_MIPS_ABIFLAGS-segment-if-present.patch
@@ -14,14 +14,14 @@ Closes: #82
Signed-off-by: Ivan A. Melnikov <iv@altlinux.org>
---
src/elf.h | 7 ++++---
- src/patchelf.cc | 11 +++++++++++
- 2 files changed, 15 insertions(+), 3 deletions(-)
+ src/patchelf.cc | 12 ++++++++++++
+ 2 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/src/elf.h b/src/elf.h
-index e4e167c..a92289d 100644
+index ae1524a..b3e567c 100644
--- a/src/elf.h
+++ b/src/elf.h
-@@ -1572,9 +1572,10 @@ typedef struct
+@@ -1574,9 +1574,10 @@ typedef struct
/* Legal values for p_type field of Elf32_Phdr. */
@@ -36,22 +36,23 @@ index e4e167c..a92289d 100644
/* Special program header types. */
diff --git a/src/patchelf.cc b/src/patchelf.cc
-index 18e1f83..31013a4 100644
+index d713728..ac8b2cd 100644
--- a/src/patchelf.cc
+++ b/src/patchelf.cc
-@@ -742,6 +742,17 @@ void ElfFile<ElfFileParamNames>::writeReplacedSections(Elf_Off & curOff,
+@@ -757,6 +757,18 @@ void ElfFile<ElfFileParamNames>::writeReplacedSections(Elf_Off & curOff,
}
}
+ /* If there is .MIPS.abiflags section, then the PT_MIPS_ABIFLAGS
+ segment must be sync'ed with it. */
+ if (sectionName == ".MIPS.abiflags") {
-+ for (unsigned int j = 0; j < phdrs.size(); ++j)
-+ if (rdi(phdrs[j].p_type) == PT_MIPS_ABIFLAGS) {
-+ phdrs[j].p_offset = shdr.sh_offset;
-+ phdrs[j].p_vaddr = phdrs[j].p_paddr = shdr.sh_addr;
-+ phdrs[j].p_filesz = phdrs[j].p_memsz = shdr.sh_size;
++ for (auto & phdr : phdrs) {
++ if (rdi(phdr.p_type) == PT_MIPS_ABIFLAGS) {
++ phdr.p_offset = shdr.sh_offset;
++ phdr.p_vaddr = phdr.p_paddr = shdr.sh_addr;
++ phdr.p_filesz = phdr.p_memsz = shdr.sh_size;
+ }
++ }
+ }
+
curOff += roundUp(i.second.size(), sectionAlignment);