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