Blame SOURCES/ltrace-0.7.91-x86-plt_map.patch

39d69a
From fba95ad936f1d8c1052259bae811f1fc07f9a215 Mon Sep 17 00:00:00 2001
39d69a
From: Petr Machata <pmachata@redhat.com>
39d69a
Date: Thu, 30 Oct 2014 01:48:17 +0100
39d69a
Subject: [PATCH] Initialize the PLT slot map correctly on x86 and x86_64
39d69a
39d69a
The PLT slot map translates relocation numbers to PLT slot numbers,
39d69a
but was actually initialized in the opposite direction.  Fix the way
39d69a
it's initialized.  This bug can be seen on glibc in particular:
39d69a
39d69a
  $ ltrace -e free ls
39d69a
  libc.so.6->free(0x5)           = <void>
39d69a
  libc.so.6->free(0x78)          = <void>
39d69a
  libc.so.6->free(0xc)           = <void>
39d69a
  libc.so.6->free(0x308)         = <void>
39d69a
39d69a
Note the nonsense values passed to free.  The problem is that these
39d69a
are not free calls at all, but malloc calls that are assigned to wrong
39d69a
PLT slots due to above bug.
39d69a
---
39d69a
 sysdeps/linux-gnu/x86/plt.c | 38 +++++++++++++++++++++-----------------
39d69a
 1 file changed, 21 insertions(+), 17 deletions(-)
39d69a
39d69a
diff --git a/sysdeps/linux-gnu/x86/plt.c b/sysdeps/linux-gnu/x86/plt.c
39d69a
index c860af6..97f6c3e 100644
39d69a
--- a/sysdeps/linux-gnu/x86/plt.c
39d69a
+++ b/sysdeps/linux-gnu/x86/plt.c
39d69a
@@ -77,6 +77,18 @@ arch_elf_init(struct ltelf *lte, struct library *lib)
39d69a
 {
39d69a
 	VECT_INIT(&lte->arch.plt_map, unsigned int);
39d69a
 
39d69a
+	if (vect_reserve(&lte->arch.plt_map, vect_size(&lte->plt_relocs)) < 0) {
39d69a
+	fail:
39d69a
+		arch_elf_destroy(lte);
39d69a
+		return -1;
39d69a
+	}
39d69a
+
39d69a
+	{
39d69a
+		unsigned int i, sz = vect_size(&lte->plt_relocs);
39d69a
+		for (i = 0; i < sz; ++i)
39d69a
+			vect_pushback (&lte->arch.plt_map, &i);
39d69a
+	}
39d69a
+
39d69a
 	/* IRELATIVE slots may make the whole situation a fair deal
39d69a
 	 * more complex.  On x86{,_64}, the PLT slots are not
39d69a
 	 * presented in the order of the corresponding relocations,
39d69a
@@ -114,43 +126,35 @@ arch_elf_init(struct ltelf *lte, struct library *lib)
39d69a
 	/* Here we scan the PLT table and initialize a map of
39d69a
 	 * relocation->slot number in lte->arch.plt_map.  */
39d69a
 
39d69a
-	size_t i;
39d69a
-	for (i = 0; i < vect_size(&lte->plt_relocs); ++i) {
39d69a
+	unsigned int i, sz = vect_size(&lte->plt_relocs);
39d69a
+	for (i = 0; i < sz; ++i) {
39d69a
 
39d69a
 		GElf_Addr offset = x86_plt_offset(i);
39d69a
-		uint32_t reloc_arg = 0;
39d69a
 
39d69a
 		uint8_t byte;
39d69a
 		if (elf_read_next_u8(lte->plt_data, &offset, &byte) < 0
39d69a
 		    || byte != 0xff
39d69a
 		    || elf_read_next_u8(lte->plt_data, &offset, &byte) < 0
39d69a
 		    || (byte != 0xa3 && byte != 0x25))
39d69a
-			goto next;
39d69a
+			continue;
39d69a
 
39d69a
 		/* Skip immediate argument in the instruction.  */
39d69a
 		offset += 4;
39d69a
 
39d69a
+		uint32_t reloc_arg;
39d69a
 		if (elf_read_next_u8(lte->plt_data, &offset, &byte) < 0
39d69a
 		    || byte != 0x68
39d69a
 		    || elf_read_next_u32(lte->plt_data,
39d69a
-					 &offset, &reloc_arg) < 0) {
39d69a
-			reloc_arg = 0;
39d69a
-			goto next;
39d69a
-		}
39d69a
+					 &offset, &reloc_arg) < 0)
39d69a
+			continue;
39d69a
 
39d69a
 		if (lte->ehdr.e_machine == EM_386) {
39d69a
-			if (reloc_arg % 8 != 0) {
39d69a
-				reloc_arg = 0;
39d69a
-				goto next;
39d69a
-			}
39d69a
+			if (reloc_arg % 8 != 0)
39d69a
+				continue;
39d69a
 			reloc_arg /= 8;
39d69a
 		}
39d69a
 
39d69a
-	next:
39d69a
-		if (VECT_PUSHBACK(&lte->arch.plt_map, &reloc_arg) < 0) {
39d69a
-			arch_elf_destroy(lte);
39d69a
-			return -1;
39d69a
-		}
39d69a
+		*VECT_ELEMENT(&lte->arch.plt_map, unsigned int, reloc_arg) = i;
39d69a
 	}
39d69a
 
39d69a
 	return 0;
39d69a
-- 
39d69a
2.1.0
39d69a