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

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