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

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