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

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