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

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