[PATCH] fix ldd segfault

Dmitry V. Levin ldv@altlinux.org
Sun Jan 13 15:04:00 GMT 2008


Hi,

_dl_check_map_versions() contains an optimization for trace mode which in
certain circumstances may lead to improper highest version index
initialization and segfault in trace mode:

Program received signal SIGSEGV, Segmentation fault.
0x0000555555561722 in _dl_check_map_versions (map=0x2aaaaaaab000, verbose=1, trace_mode=1)
    at dl-version.c:328
328                       map->l_versions[ndx].filename = &strtab[ent->vn_file];

Original bug report (in Russian):
https://bugzilla.altlinux.org/show_bug.cgi?id=11271

Proposed fix is attached.


-- 
ldv
-------------- next part --------------
2008-01-13  Dmitry V. Levin  <ldv@altlinux.org>

	* elf/dl-version.c (_dl_check_map_versions): Compare version
	inidices for all dependency symbols in trace mode as well.
	This fixes highest version index initialization in trace mode.

--- libc/elf/dl-version.c
+++ libc/elf/dl-version.c
@@ -229,15 +229,15 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode)
 	     and no stub entry was created.  This should never happen.  */
 	  assert (needed != NULL);
 
-	  /* Make sure this is no stub we created because of a missing
-	     dependency.  */
-	  if (__builtin_expect (! trace_mode, 1)
-	      || ! __builtin_expect (needed->l_faked, 0))
+	  /* NEEDED is the map for the file we need.  Now look for the
+	     dependency symbols.  */
+	  aux = (ElfW (Vernaux) *) ((char *) ent + ent->vn_aux);
+	  while (1)
 	    {
-	      /* NEEDED is the map for the file we need.  Now look for the
-		 dependency symbols.  */
-	      aux = (ElfW(Vernaux) *) ((char *) ent + ent->vn_aux);
-	      while (1)
+	      /* Make sure this is no stub we created because of a missing
+	         dependency.  */
+	      if (__builtin_expect (!trace_mode, 1)
+		  || !__builtin_expect (needed->l_faked, 0))
 		{
 		  /* Match the symbol.  */
 		  result |= match_symbol ((*map->l_name
@@ -246,18 +246,18 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode)
 					  strtab + aux->vna_name,
 					  needed->l_real, verbose,
 					  aux->vna_flags & VER_FLG_WEAK);
+		}
 
-		  /* Compare the version index.  */
-		  if ((unsigned int) (aux->vna_other & 0x7fff) > ndx_high)
-		    ndx_high = aux->vna_other & 0x7fff;
+	      /* Compare the version index.  */
+	      if ((unsigned int) (aux->vna_other & 0x7fff) > ndx_high)
+		ndx_high = aux->vna_other & 0x7fff;
 
-		  if (aux->vna_next == 0)
-		    /* No more symbols.  */
-		    break;
+	      if (aux->vna_next == 0)
+		/* No more symbols.  */
+		break;
 
-		  /* Next symbol.  */
-		  aux = (ElfW(Vernaux) *) ((char *) aux + aux->vna_next);
-		}
+	      /* Next symbol.  */
+	      aux = (ElfW(Vernaux) *) ((char *) aux + aux->vna_next);
 	    }
 
 	  if (ent->vn_next == 0)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/libc-alpha/attachments/20080113/cc5aef9b/attachment.sig>


More information about the Libc-alpha mailing list