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

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