1c5bb4e
From 64a0206c451920b72a9c5721a6f2427baf99e3dd Mon Sep 17 00:00:00 2001
e2ce63b
From: Ian Jackson <ian.jackson@eu.citrix.com>
1c5bb4e
Date: Fri, 14 Jun 2013 16:45:36 +0100
1c5bb4e
Subject: [PATCH 01/21] libelf: abolish libelf-relocate.c
e2ce63b
e2ce63b
This file is not actually used.  It's not built in Xen's instance of
e2ce63b
libelf; in libxc's it's built but nothing in it is called.  Do not
e2ce63b
compile it in libxc, and delete it.
e2ce63b
e2ce63b
This reduces the amount of work we need to do in forthcoming patches
e2ce63b
to libelf (particularly since as libelf-relocate.c is not used it is
e2ce63b
probably full of bugs).
e2ce63b
1c5bb4e
This is part of the fix to a security issue, XSA-55.
1c5bb4e
e2ce63b
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
e2ce63b
Acked-by: Ian Campbell <ian.campbell@citrix.com>
e2ce63b
---
e2ce63b
 tools/libxc/Makefile                |    2 +-
e2ce63b
 xen/common/libelf/libelf-relocate.c |  372 -----------------------------------
e2ce63b
 2 files changed, 1 insertions(+), 373 deletions(-)
e2ce63b
 delete mode 100644 xen/common/libelf/libelf-relocate.c
e2ce63b
e2ce63b
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
e2ce63b
index 9942c3a..6f5c307 100644
e2ce63b
--- a/tools/libxc/Makefile
e2ce63b
+++ b/tools/libxc/Makefile
e2ce63b
@@ -50,7 +50,7 @@ vpath %.c ../../xen/common/libelf
e2ce63b
 CFLAGS += -I../../xen/common/libelf
e2ce63b
 
e2ce63b
 GUEST_SRCS-y += libelf-tools.c libelf-loader.c
e2ce63b
-GUEST_SRCS-y += libelf-dominfo.c libelf-relocate.c
e2ce63b
+GUEST_SRCS-y += libelf-dominfo.c
e2ce63b
 
e2ce63b
 # new domain builder
e2ce63b
 GUEST_SRCS-y                 += xc_dom_core.c xc_dom_boot.c
e2ce63b
diff --git a/xen/common/libelf/libelf-relocate.c b/xen/common/libelf/libelf-relocate.c
e2ce63b
deleted file mode 100644
e2ce63b
index 7ef4b01..0000000
e2ce63b
--- a/xen/common/libelf/libelf-relocate.c
e2ce63b
+++ /dev/null
e2ce63b
@@ -1,372 +0,0 @@
e2ce63b
-/*
e2ce63b
- * ELF relocation code (not used by xen kernel right now).
e2ce63b
- *
e2ce63b
- * This library is free software; you can redistribute it and/or
e2ce63b
- * modify it under the terms of the GNU Lesser General Public
e2ce63b
- * License as published by the Free Software Foundation;
e2ce63b
- * version 2.1 of the License.
e2ce63b
- *
e2ce63b
- * This library is distributed in the hope that it will be useful,
e2ce63b
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
e2ce63b
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
e2ce63b
- * Lesser General Public License for more details.
e2ce63b
- *
e2ce63b
- * You should have received a copy of the GNU Lesser General Public
e2ce63b
- * License along with this library; if not, write to the Free Software
e2ce63b
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
e2ce63b
- */
e2ce63b
-
e2ce63b
-#include "libelf-private.h"
e2ce63b
-
e2ce63b
-/* ------------------------------------------------------------------------ */
e2ce63b
-
e2ce63b
-static const char *rel_names_i386[] = {
e2ce63b
-    "R_386_NONE",
e2ce63b
-    "R_386_32",
e2ce63b
-    "R_386_PC32",
e2ce63b
-    "R_386_GOT32",
e2ce63b
-    "R_386_PLT32",
e2ce63b
-    "R_386_COPY",
e2ce63b
-    "R_386_GLOB_DAT",
e2ce63b
-    "R_386_JMP_SLOT",
e2ce63b
-    "R_386_RELATIVE",
e2ce63b
-    "R_386_GOTOFF",
e2ce63b
-    "R_386_GOTPC",
e2ce63b
-    "R_386_32PLT",
e2ce63b
-    "R_386_TLS_TPOFF",
e2ce63b
-    "R_386_TLS_IE",
e2ce63b
-    "R_386_TLS_GOTIE",
e2ce63b
-    "R_386_TLS_LE",
e2ce63b
-    "R_386_TLS_GD",
e2ce63b
-    "R_386_TLS_LDM",
e2ce63b
-    "R_386_16",
e2ce63b
-    "R_386_PC16",
e2ce63b
-    "R_386_8",
e2ce63b
-    "R_386_PC8",
e2ce63b
-    "R_386_TLS_GD_32",
e2ce63b
-    "R_386_TLS_GD_PUSH",
e2ce63b
-    "R_386_TLS_GD_CALL",
e2ce63b
-    "R_386_TLS_GD_POP",
e2ce63b
-    "R_386_TLS_LDM_32",
e2ce63b
-    "R_386_TLS_LDM_PUSH",
e2ce63b
-    "R_386_TLS_LDM_CALL",
e2ce63b
-    "R_386_TLS_LDM_POP",
e2ce63b
-    "R_386_TLS_LDO_32",
e2ce63b
-    "R_386_TLS_IE_32",
e2ce63b
-    "R_386_TLS_LE_32",
e2ce63b
-    "R_386_TLS_DTPMOD32",
e2ce63b
-    "R_386_TLS_DTPOFF32",
e2ce63b
-    "R_386_TLS_TPOFF32",
e2ce63b
-};
e2ce63b
-
e2ce63b
-static int elf_reloc_i386(struct elf_binary *elf, int type,
e2ce63b
-                          uint64_t addr, uint64_t value)
e2ce63b
-{
e2ce63b
-    void *ptr = elf_get_ptr(elf, addr);
e2ce63b
-    uint32_t *u32;
e2ce63b
-
e2ce63b
-    switch ( type )
e2ce63b
-    {
e2ce63b
-    case 1 /* R_386_32 */ :
e2ce63b
-        u32 = ptr;
e2ce63b
-        *u32 += elf->reloc_offset;
e2ce63b
-        break;
e2ce63b
-    case 2 /* R_386_PC32 */ :
e2ce63b
-        /* nothing */
e2ce63b
-        break;
e2ce63b
-    default:
e2ce63b
-        return -1;
e2ce63b
-    }
e2ce63b
-    return 0;
e2ce63b
-}
e2ce63b
-
e2ce63b
-/* ------------------------------------------------------------------------ */
e2ce63b
-
e2ce63b
-static const char *rel_names_x86_64[] = {
e2ce63b
-    "R_X86_64_NONE",
e2ce63b
-    "R_X86_64_64",
e2ce63b
-    "R_X86_64_PC32",
e2ce63b
-    "R_X86_64_GOT32",
e2ce63b
-    "R_X86_64_PLT32",
e2ce63b
-    "R_X86_64_COPY",
e2ce63b
-    "R_X86_64_GLOB_DAT",
e2ce63b
-    "R_X86_64_JUMP_SLOT",
e2ce63b
-    "R_X86_64_RELATIVE",
e2ce63b
-    "R_X86_64_GOTPCREL",
e2ce63b
-    "R_X86_64_32",
e2ce63b
-    "R_X86_64_32S",
e2ce63b
-    "R_X86_64_16",
e2ce63b
-    "R_X86_64_PC16",
e2ce63b
-    "R_X86_64_8",
e2ce63b
-    "R_X86_64_PC8",
e2ce63b
-    "R_X86_64_DTPMOD64",
e2ce63b
-    "R_X86_64_DTPOFF64",
e2ce63b
-    "R_X86_64_TPOFF64",
e2ce63b
-    "R_X86_64_TLSGD",
e2ce63b
-    "R_X86_64_TLSLD",
e2ce63b
-    "R_X86_64_DTPOFF32",
e2ce63b
-    "R_X86_64_GOTTPOFF",
e2ce63b
-    "R_X86_64_TPOFF32",
e2ce63b
-};
e2ce63b
-
e2ce63b
-static int elf_reloc_x86_64(struct elf_binary *elf, int type,
e2ce63b
-                            uint64_t addr, uint64_t value)
e2ce63b
-{
e2ce63b
-    void *ptr = elf_get_ptr(elf, addr);
e2ce63b
-    uint64_t *u64;
e2ce63b
-    uint32_t *u32;
e2ce63b
-    int32_t *s32;
e2ce63b
-
e2ce63b
-    switch ( type )
e2ce63b
-    {
e2ce63b
-    case 1 /* R_X86_64_64 */ :
e2ce63b
-        u64 = ptr;
e2ce63b
-        value += elf->reloc_offset;
e2ce63b
-        *u64 = value;
e2ce63b
-        break;
e2ce63b
-    case 2 /* R_X86_64_PC32 */ :
e2ce63b
-        u32 = ptr;
e2ce63b
-        *u32 = value - addr;
e2ce63b
-        if ( *u32 != (uint32_t)(value - addr) )
e2ce63b
-        {
e2ce63b
-            elf_err(elf, "R_X86_64_PC32 overflow: 0x%" PRIx32
e2ce63b
-                    " != 0x%" PRIx32 "\n",
e2ce63b
-                    *u32, (uint32_t) (value - addr));
e2ce63b
-            return -1;
e2ce63b
-        }
e2ce63b
-        break;
e2ce63b
-    case 10 /* R_X86_64_32 */ :
e2ce63b
-        u32 = ptr;
e2ce63b
-        value += elf->reloc_offset;
e2ce63b
-        *u32 = value;
e2ce63b
-        if ( *u32 != value )
e2ce63b
-        {
e2ce63b
-            elf_err(elf, "R_X86_64_32 overflow: 0x%" PRIx32
e2ce63b
-                    " != 0x%" PRIx64 "\n",
e2ce63b
-                    *u32, value);
e2ce63b
-            return -1;
e2ce63b
-        }
e2ce63b
-        break;
e2ce63b
-    case 11 /* R_X86_64_32S */ :
e2ce63b
-        s32 = ptr;
e2ce63b
-        value += elf->reloc_offset;
e2ce63b
-        *s32 = value;
e2ce63b
-        if ( *s32 != (int64_t) value )
e2ce63b
-        {
e2ce63b
-            elf_err(elf, "R_X86_64_32S overflow: 0x%" PRIx32
e2ce63b
-                    " != 0x%" PRIx64 "\n",
e2ce63b
-                    *s32, (int64_t) value);
e2ce63b
-            return -1;
e2ce63b
-        }
e2ce63b
-        break;
e2ce63b
-    default:
e2ce63b
-        return -1;
e2ce63b
-    }
e2ce63b
-    return 0;
e2ce63b
-}
e2ce63b
-
e2ce63b
-/* ------------------------------------------------------------------------ */
e2ce63b
-
e2ce63b
-static struct relocs {
e2ce63b
-    const char **names;
e2ce63b
-    int count;
e2ce63b
-    int (*func) (struct elf_binary * elf, int type, uint64_t addr,
e2ce63b
-                 uint64_t value);
e2ce63b
-} relocs[] =
e2ce63b
-/* *INDENT-OFF* */
e2ce63b
-{
e2ce63b
-    [EM_386] = {
e2ce63b
-        .names = rel_names_i386,
e2ce63b
-        .count = sizeof(rel_names_i386) / sizeof(rel_names_i386[0]),
e2ce63b
-        .func = elf_reloc_i386,
e2ce63b
-    },
e2ce63b
-    [EM_X86_64] = {
e2ce63b
-        .names = rel_names_x86_64,
e2ce63b
-        .count = sizeof(rel_names_x86_64) / sizeof(rel_names_x86_64[0]),
e2ce63b
-        .func = elf_reloc_x86_64,
e2ce63b
-    }
e2ce63b
-};
e2ce63b
-/* *INDENT-ON* */
e2ce63b
-
e2ce63b
-/* ------------------------------------------------------------------------ */
e2ce63b
-
e2ce63b
-static const char *rela_name(int machine, int type)
e2ce63b
-{
e2ce63b
-    if ( machine > sizeof(relocs) / sizeof(relocs[0]) )
e2ce63b
-        return "unknown mach";
e2ce63b
-    if ( !relocs[machine].names )
e2ce63b
-        return "unknown mach";
e2ce63b
-    if ( type > relocs[machine].count )
e2ce63b
-        return "unknown rela";
e2ce63b
-    return relocs[machine].names[type];
e2ce63b
-}
e2ce63b
-
e2ce63b
-static int elf_reloc_section(struct elf_binary *elf,
e2ce63b
-                             const elf_shdr * rels,
e2ce63b
-                             const elf_shdr * sect, const elf_shdr * syms)
e2ce63b
-{
e2ce63b
-    const void *ptr, *end;
e2ce63b
-    const elf_shdr *shdr;
e2ce63b
-    const elf_rela *rela;
e2ce63b
-    const elf_rel *rel;
e2ce63b
-    const elf_sym *sym;
e2ce63b
-    uint64_t s_type;
e2ce63b
-    uint64_t r_offset;
e2ce63b
-    uint64_t r_info;
e2ce63b
-    uint64_t r_addend;
e2ce63b
-    int r_type, r_sym;
e2ce63b
-    size_t rsize;
e2ce63b
-    uint64_t shndx, sbase, addr, value;
e2ce63b
-    const char *sname;
e2ce63b
-    int machine;
e2ce63b
-
e2ce63b
-    machine = elf_uval(elf, elf->ehdr, e_machine);
e2ce63b
-    if ( (machine >= (sizeof(relocs) / sizeof(relocs[0]))) ||
e2ce63b
-         (relocs[machine].func == NULL) )
e2ce63b
-    {
e2ce63b
-        elf_err(elf, "%s: can't handle machine %d\n",
e2ce63b
-                __FUNCTION__, machine);
e2ce63b
-        return -1;
e2ce63b
-    }
e2ce63b
-    if ( elf_swap(elf) )
e2ce63b
-    {
e2ce63b
-        elf_err(elf, "%s: non-native byte order, relocation not supported\n",
e2ce63b
-                __FUNCTION__);
e2ce63b
-        return -1;
e2ce63b
-    }
e2ce63b
-
e2ce63b
-    s_type = elf_uval(elf, rels, sh_type);
e2ce63b
-    rsize = (SHT_REL == s_type) ? elf_size(elf, rel) : elf_size(elf, rela);
e2ce63b
-    ptr = elf_section_start(elf, rels);
e2ce63b
-    end = elf_section_end(elf, rels);
e2ce63b
-
e2ce63b
-    for ( ; ptr < end; ptr += rsize )
e2ce63b
-    {
e2ce63b
-        switch ( s_type )
e2ce63b
-        {
e2ce63b
-        case SHT_REL:
e2ce63b
-            rel = ptr;
e2ce63b
-            r_offset = elf_uval(elf, rel, r_offset);
e2ce63b
-            r_info = elf_uval(elf, rel, r_info);
e2ce63b
-            r_addend = 0;
e2ce63b
-            break;
e2ce63b
-        case SHT_RELA:
e2ce63b
-            rela = ptr;
e2ce63b
-            r_offset = elf_uval(elf, rela, r_offset);
e2ce63b
-            r_info = elf_uval(elf, rela, r_info);
e2ce63b
-            r_addend = elf_uval(elf, rela, r_addend);
e2ce63b
-            break;
e2ce63b
-        default:
e2ce63b
-            /* can't happen */
e2ce63b
-            return -1;
e2ce63b
-        }
e2ce63b
-        if ( elf_64bit(elf) )
e2ce63b
-        {
e2ce63b
-            r_type = ELF64_R_TYPE(r_info);
e2ce63b
-            r_sym = ELF64_R_SYM(r_info);
e2ce63b
-        }
e2ce63b
-        else
e2ce63b
-        {
e2ce63b
-            r_type = ELF32_R_TYPE(r_info);
e2ce63b
-            r_sym = ELF32_R_SYM(r_info);
e2ce63b
-        }
e2ce63b
-
e2ce63b
-        sym = elf_sym_by_index(elf, r_sym);
e2ce63b
-        shndx = elf_uval(elf, sym, st_shndx);
e2ce63b
-        switch ( shndx )
e2ce63b
-        {
e2ce63b
-        case SHN_UNDEF:
e2ce63b
-            sname = "*UNDEF*";
e2ce63b
-            sbase = 0;
e2ce63b
-            break;
e2ce63b
-        case SHN_COMMON:
e2ce63b
-            elf_err(elf, "%s: invalid section: %" PRId64 "\n",
e2ce63b
-                    __FUNCTION__, shndx);
e2ce63b
-            return -1;
e2ce63b
-        case SHN_ABS:
e2ce63b
-            sname = "*ABS*";
e2ce63b
-            sbase = 0;
e2ce63b
-            break;
e2ce63b
-        default:
e2ce63b
-            shdr = elf_shdr_by_index(elf, shndx);
e2ce63b
-            if ( shdr == NULL )
e2ce63b
-            {
e2ce63b
-                elf_err(elf, "%s: invalid section: %" PRId64 "\n",
e2ce63b
-                        __FUNCTION__, shndx);
e2ce63b
-                return -1;
e2ce63b
-            }
e2ce63b
-            sname = elf_section_name(elf, shdr);
e2ce63b
-            sbase = elf_uval(elf, shdr, sh_addr);
e2ce63b
-        }
e2ce63b
-
e2ce63b
-        addr = r_offset;
e2ce63b
-        value = elf_uval(elf, sym, st_value);
e2ce63b
-        value += r_addend;
e2ce63b
-
e2ce63b
-        if ( elf->log_callback && (elf->verbose > 1) )
e2ce63b
-        {
e2ce63b
-            uint64_t st_name = elf_uval(elf, sym, st_name);
e2ce63b
-            const char *name = st_name ? elf->sym_strtab + st_name : "*NONE*";
e2ce63b
-
e2ce63b
-            elf_msg(elf,
e2ce63b
-                    "%s: type %s [%d], off 0x%" PRIx64 ", add 0x%" PRIx64 ","
e2ce63b
-                    " sym %s [0x%" PRIx64 "], sec %s [0x%" PRIx64 "]"
e2ce63b
-                    "  ->  addr 0x%" PRIx64 " value 0x%" PRIx64 "\n",
e2ce63b
-                    __FUNCTION__, rela_name(machine, r_type), r_type, r_offset,
e2ce63b
-                    r_addend, name, elf_uval(elf, sym, st_value), sname, sbase,
e2ce63b
-                    addr, value);
e2ce63b
-        }
e2ce63b
-
e2ce63b
-        if ( relocs[machine].func(elf, r_type, addr, value) == -1 )
e2ce63b
-        {
e2ce63b
-            elf_err(elf, "%s: unknown/unsupported reloc type %s [%d]\n",
e2ce63b
-                    __FUNCTION__, rela_name(machine, r_type), r_type);
e2ce63b
-            return -1;
e2ce63b
-        }
e2ce63b
-    }
e2ce63b
-    return 0;
e2ce63b
-}
e2ce63b
-
e2ce63b
-int elf_reloc(struct elf_binary *elf)
e2ce63b
-{
e2ce63b
-    const elf_shdr *rels, *sect, *syms;
e2ce63b
-    uint64_t i, count, type;
e2ce63b
-
e2ce63b
-    count = elf_shdr_count(elf);
e2ce63b
-    for ( i = 0; i < count; i++ )
e2ce63b
-    {
e2ce63b
-        rels = elf_shdr_by_index(elf, i);
e2ce63b
-        type = elf_uval(elf, rels, sh_type);
e2ce63b
-        if ( (type != SHT_REL) && (type != SHT_RELA) )
e2ce63b
-            continue;
e2ce63b
-
e2ce63b
-        sect = elf_shdr_by_index(elf, elf_uval(elf, rels, sh_info));
e2ce63b
-        syms = elf_shdr_by_index(elf, elf_uval(elf, rels, sh_link));
e2ce63b
-        if ( NULL == sect || NULL == syms )
e2ce63b
-            continue;
e2ce63b
-
e2ce63b
-        if ( !(elf_uval(elf, sect, sh_flags) & SHF_ALLOC) )
e2ce63b
-        {
e2ce63b
-            elf_msg(elf, "%s: relocations for %s, skipping\n",
e2ce63b
-                    __FUNCTION__, elf_section_name(elf, sect));
e2ce63b
-            continue;
e2ce63b
-        }
e2ce63b
-
e2ce63b
-        elf_msg(elf, "%s: relocations for %s @ 0x%" PRIx64 "\n",
e2ce63b
-                __FUNCTION__, elf_section_name(elf, sect),
e2ce63b
-                elf_uval(elf, sect, sh_addr));
e2ce63b
-        if ( elf_reloc_section(elf, rels, sect, syms) != 0 )
e2ce63b
-            return -1;
e2ce63b
-    }
e2ce63b
-    return 0;
e2ce63b
-}
e2ce63b
-
e2ce63b
-/*
e2ce63b
- * Local variables:
e2ce63b
- * mode: C
e2ce63b
- * c-set-style: "BSD"
e2ce63b
- * c-basic-offset: 4
e2ce63b
- * tab-width: 4
e2ce63b
- * indent-tabs-mode: nil
e2ce63b
- * End:
e2ce63b
- */
e2ce63b
-- 
e2ce63b
1.7.2.5
e2ce63b