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

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