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

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