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

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