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

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