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

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