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