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

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