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

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