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