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

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