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