Bug#820335: Segfaults caused by new DT_MIPS_RLD_MAP_REL tag and RPATH removers

Aurelien Jarno <[email protected]>
Newsgroups gmane.linux.debian.ports.mips
Message-ID <20160408175621.GA11075__34229.8527750701$1460139120$gmane$org@aurel32.net>
control: tag -1 + patch

On 2016-04-07 15:46, Mathieu Malaterre wrote:
> Package: src:chrpath
> Version: 0.16-1
> 
> Hi,
> 
> I've managed to find the cause of the openmpi segfault (#818909). It
> might affect a number of different packages.
> 
> The segfault is caused by the interaction of the
> new DT_MIPS_RLD_MAP_REL dynamic tag (from binutils 2.26) and chrpath.
> Unlike all other tags, this tag is relative to the offset of the tag
> within the executable. chrpath is used to remove rpaths from ELF files.
> It does this by moving all of the other dynamic tags up one entry, but
> since the DT_MIPS_RLD_MAP_REL is not updated, it now points to an
> incorrect offset. The dynamic linker will then overwrite some other
> memory when processing the DT_MIPS_RLD_MAP_REL tag.

Please find below a patch to correctly handle this tag in chrpath. If
you are fine with the patch, a quick upload would be appreciated as
chrpath currently generates broken binaries. Thanks!

Aurelien


--- chrpath-0.16.orig/killrpath.c
+++ chrpath-0.16/killrpath.c
@@ -73,10 +73,26 @@
    dynpos = 0;
    for (i = 0; DYNSS(i, d_tag) != DT_NULL; i++)
      {
-       if (is_e32())
+       if (is_e32()) {
         ((Elf32_Dyn *)dyns)[dynpos] = ((Elf32_Dyn *)dyns)[i];
-       else
+#ifdef DT_MIPS_RLD_MAP_REL
+        /* DT_MIPS_RLD_MAP_REL is relative to the offset of the tag.
+           Adjust it consequently.  */
+        if (DYNSS(i, d_tag) == DT_MIPS_RLD_MAP_REL)
+         ((Elf32_Dyn *)dyns)[dynpos].d_un.d_val =
+          DO_SWAPU32(DYNSU(i, d_un.d_val) +
+          (i - dynpos) * sizeof(Elf32_Dyn));
+#endif
+       } else {
         ((Elf64_Dyn *)dyns)[dynpos] = ((Elf64_Dyn *)dyns)[i];
+#ifdef DT_MIPS_RLD_MAP_REL
+        /* Ditto */
+        if (DYNSS(i, d_tag) == DT_MIPS_RLD_MAP_REL)
+         ((Elf64_Dyn *)dyns)[dynpos].d_un.d_val =
+          DO_SWAPU64(DYNSU(i, d_un.d_val) +
+          (i - dynpos) * sizeof(Elf64_Dyn));
+#endif
+       }
        if ( ! elf_dynpath_tag(DYNSS(i, d_tag)) )
         dynpos++;
      }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.