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

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