Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 20 Jan 2019 03:53:42 +0000 (UTC)
From:      Justin Hibbits <jhibbits@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r343207 - stable/12/lib/libc/gen
Message-ID:  <201901200353.x0K3rggs000540@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhibbits
Date: Sun Jan 20 03:53:42 2019
New Revision: 343207
URL: https://svnweb.freebsd.org/changeset/base/343207

Log:
  MFC r341387:
  
  Fix PowerPC64 ELFv1-specific problem in __elf_phdr_match_addr() leading to crash
  in threaded programs that unload libraries.
  
  Summary:
  The GNOME update to 3.28 exposed a bug in __elf_phdr_match_addr(), which leads
  to a crash when building devel/libsoup on powerpc64.
  
  Due to __elf_phdr_match_addr() limiting its search to PF_X sections, on the
  PPC64 ELFv1 ABI, it was never matching function pointers properly.
  
  This meant that libthr was never cleaning up its atfork list in
  __pthread_cxa_finalize(), so if a library with an atfork handler was unloaded,
  libthr would crash on the next fork.
  
  Normally, the null pointer check it does before calling the handler would avoid
  this crash, but, due to PPC64 ELFv1 using function descriptors instead of raw
  function pointers, a null check against the pointer itself is insufficient, as
  the pointer itself was not null, it was just pointing at a function descriptor
  that had been zeroed. (Which is an ABI violation.)
  
  Calling a zeroed function descriptor on PPC64 ELFv1 causes a jump to address 0
  with a zeroed r2 and r11.

Modified:
  stable/12/lib/libc/gen/elf_utils.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/lib/libc/gen/elf_utils.c
==============================================================================
--- stable/12/lib/libc/gen/elf_utils.c	Sun Jan 20 03:30:04 2019	(r343206)
+++ stable/12/lib/libc/gen/elf_utils.c	Sun Jan 20 03:53:42 2019	(r343207)
@@ -47,8 +47,21 @@ __elf_phdr_match_addr(struct dl_phdr_info *phdr_info, 
 
 	for (i = 0; i < phdr_info->dlpi_phnum; i++) {
 		ph = &phdr_info->dlpi_phdr[i];
-		if (ph->p_type != PT_LOAD || (ph->p_flags & PF_X) == 0)
+		if (ph->p_type != PT_LOAD)
 			continue;
+
+		/* ELFv1 ABI for powerpc64 passes function descriptor
+		 * pointers around, not function pointers.  The function
+		 * descriptors live in .opd, which is a non-executable segment.
+		 * The PF_X check would therefore make all address checks fail,
+		 * causing a crash in some instances.  Don't skip over
+		 * non-executable segments in the ELFv1 powerpc64 case.
+		 */
+#if !defined(__powerpc64__) || (defined(_CALL_ELF) && _CALL_ELF == 2)
+		if ((ph->p_flags & PF_X) == 0)
+			continue;
+#endif
+
 		if (phdr_info->dlpi_addr + ph->p_vaddr <= (uintptr_t)addr &&
 		    (uintptr_t)addr + sizeof(addr) < phdr_info->dlpi_addr +
 		    ph->p_vaddr + ph->p_memsz)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201901200353.x0K3rggs000540>