[xen] fixes for 4 security advisories including CVE-2013-2076, CVE-2013-2077, CVE-2013-2078
myoung
myoung at fedoraproject.org
Tue Jun 4 19:55:50 UTC 2013
commit 73efd6be48c08d5f0779d4406c250f35174e1c04
Author: Michael Young <m.a.young at durham.ac.uk>
Date: Tue Jun 4 20:50:37 2013 +0100
fixes for 4 security advisories including CVE-2013-2076, CVE-2013-2077,
CVE-2013-2078
xen.spec | 50 +-
xsa52-4.2-unstable.patch | 46 +
xsa53-4.2.patch | 57 +
xsa54.patch | 24 +
...-4.20001-libelf-abolish-libelf-relocate.c.patch | 415 +++++++
...2-libxc-introduce-xc_dom_seg_to_ptr_pages.patch | 50 +
...struct-elf_binary-parameter-to-elf_load_i.patch | 53 +
...lf-abolish-elf_sval-and-elf_access_signed.patch | 84 ++
...-include-of-asm-guest_access.h-to-top-of-.patch | 48 +
...om_load_elf_symtab-Do-not-use-syms-uninit.patch | 41 +
...oduce-macros-for-memory-access-and-pointe.patch | 1208 ++++++++++++++++++++
...ls-readnotes-adjust-print_l1_mfn_valid_no.patch | 58 +
...elf-check-nul-terminated-strings-properly.patch | 203 ++++
...4.20010-libelf-check-all-pointer-accesses.patch | 820 +++++++++++++
...ck-pointer-references-in-elf_is_elfbinary.patch | 108 ++
...lf-Make-all-callers-call-elf_check_broken.patch | 256 +++++
...-4.20013-libelf-use-C99-bool-for-booleans.patch | 251 ++++
...4.20014-libelf-use-only-unsigned-integers.patch | 765 +++++++++++++
...20015-libelf-check-loops-for-running-away.patch | 195 ++++
xsa55-4.20016-libelf-abolish-obsolete-macros.patch | 406 +++++++
20 files changed, 5137 insertions(+), 1 deletions(-)
---
diff --git a/xen.spec b/xen.spec
index 288bd2e..976a374 100644
--- a/xen.spec
+++ b/xen.spec
@@ -27,7 +27,7 @@
Summary: Xen is a virtual machine monitor
Name: xen
Version: 4.2.2
-Release: 5%{?dist}
+Release: 6%{?dist}
Group: Development/Libraries
License: GPLv2+ and LGPLv2+ and BSD
URL: http://xen.org/
@@ -88,6 +88,25 @@ Patch71: xsa45-4.2-07-mm-error-paths-preemptible.patch
Patch72: xsa49-4.2.patch
Patch73: xen.pygrubtitlefix.patch
Patch74: xsa56.patch
+Patch75: xsa52-4.2-unstable.patch
+Patch76: xsa53-4.2.patch
+Patch77: xsa54.patch
+Patch78: xsa55-4.20001-libelf-abolish-libelf-relocate.c.patch
+Patch79: xsa55-4.20002-libxc-introduce-xc_dom_seg_to_ptr_pages.patch
+Patch80: xsa55-4.20003-libelf-add-struct-elf_binary-parameter-to-elf_load_i.patch
+Patch81: xsa55-4.20004-libelf-abolish-elf_sval-and-elf_access_signed.patch
+Patch82: xsa55-4.20005-libelf-move-include-of-asm-guest_access.h-to-top-of-.patch
+Patch83: xsa55-4.20006-libelf-xc_dom_load_elf_symtab-Do-not-use-syms-uninit.patch
+Patch84: xsa55-4.20007-libelf-introduce-macros-for-memory-access-and-pointe.patch
+Patch85: xsa55-4.20008-tools-xcutils-readnotes-adjust-print_l1_mfn_valid_no.patch
+Patch86: xsa55-4.20009-libelf-check-nul-terminated-strings-properly.patch
+Patch87: xsa55-4.20010-libelf-check-all-pointer-accesses.patch
+Patch88: xsa55-4.20011-libelf-Check-pointer-references-in-elf_is_elfbinary.patch
+Patch89: xsa55-4.20012-libelf-Make-all-callers-call-elf_check_broken.patch
+Patch90: xsa55-4.20013-libelf-use-C99-bool-for-booleans.patch
+Patch91: xsa55-4.20014-libelf-use-only-unsigned-integers.patch
+Patch92: xsa55-4.20015-libelf-check-loops-for-running-away.patch
+Patch93: xsa55-4.20016-libelf-abolish-obsolete-macros.patch
Patch100: xen-configure-xend.patch
@@ -267,6 +286,25 @@ manage Xen virtual machines.
%patch72 -p1
%patch73 -p1
%patch74 -p1
+%patch75 -p1
+%patch76 -p1
+%patch77 -p1
+%patch78 -p1
+%patch79 -p1
+%patch80 -p1
+%patch81 -p1
+%patch82 -p1
+%patch83 -p1
+%patch84 -p1
+%patch85 -p1
+%patch86 -p1
+%patch87 -p1
+%patch88 -p1
+%patch89 -p1
+%patch90 -p1
+%patch91 -p1
+%patch92 -p1
+%patch93 -p1
%patch100 -p1
@@ -756,6 +794,16 @@ rm -rf %{buildroot}
%endif
%changelog
+* Tue Jun 04 2013 Michael Young <m.a.young at durham.ac.uk> - 4.2.2-6
+- Information leak on XSAVE/XRSTOR capable AMD CPUs
+ [XSA-52, CVE-2013-2076] (#970206)
+- Hypervisor crash due to missing exception recovery on XRSTOR
+ [XSA-53, CVE-2013-2077] (#970204)
+- Hypervisor crash due to missing exception recovery on XSETBV
+ [XSA-54, CVE-2013-2078] (#970202)
+- Multiple vulnerabilities in libelf PV kernel handling
+ [XSA-55] (#970640)
+
* Fri May 17 2013 Michael Young <m.a.young at durham.ac.uk> - 4.2.2-5
- xend toolstack doesn't check bounds for VCPU affinity
[XSA-56, CVE-2013-2072] (#964241)
diff --git a/xsa52-4.2-unstable.patch b/xsa52-4.2-unstable.patch
new file mode 100644
index 0000000..14db8a8
--- /dev/null
+++ b/xsa52-4.2-unstable.patch
@@ -0,0 +1,46 @@
+x86/xsave: fix information leak on AMD CPUs
+
+Just like for FXSAVE/FXRSTOR, XSAVE/XRSTOR also don't save/restore the
+last instruction and operand pointers as well as the last opcode if
+there's no pending unmasked exception (see CVE-2006-1056 and commit
+9747:4d667a139318).
+
+While the FXSR solution sits in the save path, I prefer to have this in
+the restore path because there the handling is simpler (namely in the
+context of the pending changes to properly save the selector values for
+32-bit guest code).
+
+Also this is using FFREE instead of EMMS, as it doesn't seem unlikely
+that in the future we may see CPUs with x87 and SSE/AVX but no MMX
+support. The goal here anyway is just to avoid an FPU stack overflow.
+I would have preferred to use FFREEP instead of FFREE (freeing two
+stack slots at once), but AMD doesn't document that instruction.
+
+This is CVE-2013-2076 / XSA-52.
+
+Signed-off-by: Jan Beulich <jbeulich at suse.com>
+
+--- a/xen/arch/x86/xstate.c
++++ b/xen/arch/x86/xstate.c
+@@ -78,6 +78,21 @@ void xrstor(struct vcpu *v, uint64_t mas
+
+ struct xsave_struct *ptr = v->arch.xsave_area;
+
++ /*
++ * AMD CPUs don't save/restore FDP/FIP/FOP unless an exception
++ * is pending. Clear the x87 state here by setting it to fixed
++ * values. The hypervisor data segment can be sometimes 0 and
++ * sometimes new user value. Both should be ok. Use the FPU saved
++ * data block as a safe address because it should be in L1.
++ */
++ if ( (mask & ptr->xsave_hdr.xstate_bv & XSTATE_FP) &&
++ !(ptr->fpu_sse.fsw & 0x0080) &&
++ boot_cpu_data.x86_vendor == X86_VENDOR_AMD )
++ asm volatile ( "fnclex\n\t" /* clear exceptions */
++ "ffree %%st(7)\n\t" /* clear stack tag */
++ "fildl %0" /* load to clear state */
++ : : "m" (ptr->fpu_sse) );
++
+ asm volatile (
+ ".byte " REX_PREFIX "0x0f,0xae,0x2f"
+ :
diff --git a/xsa53-4.2.patch b/xsa53-4.2.patch
new file mode 100644
index 0000000..eb8e79b
--- /dev/null
+++ b/xsa53-4.2.patch
@@ -0,0 +1,57 @@
+x86/xsave: recover from faults on XRSTOR
+
+Just like FXRSTOR, XRSTOR can raise #GP if bad content is being passed
+to it in the memory block (i.e. aspects not under the control of the
+hypervisor, other than e.g. proper alignment of the block).
+
+Also correct the comment explaining why FXRSTOR needs exception
+recovery code to not wrongly state that this can only be a result of
+the control tools passing a bad image.
+
+This is CVE-2013-2077 / XSA-53.
+
+Signed-off-by: Jan Beulich <jbeulich at suse.com>
+
+--- a/xen/arch/x86/i387.c
++++ b/xen/arch/x86/i387.c
+@@ -53,7 +53,7 @@ static inline void fpu_fxrstor(struct vc
+ /*
+ * FXRSTOR can fault if passed a corrupted data block. We handle this
+ * possibility, which may occur if the block was passed to us by control
+- * tools, by silently clearing the block.
++ * tools or through VCPUOP_initialise, by silently clearing the block.
+ */
+ asm volatile (
+ #ifdef __i386__
+--- a/xen/arch/x86/xstate.c
++++ b/xen/arch/x86/xstate.c
+@@ -93,10 +93,25 @@ void xrstor(struct vcpu *v, uint64_t mas
+ "fildl %0" /* load to clear state */
+ : : "m" (ptr->fpu_sse) );
+
+- asm volatile (
+- ".byte " REX_PREFIX "0x0f,0xae,0x2f"
+- :
+- : "m" (*ptr), "a" (lmask), "d" (hmask), "D"(ptr) );
++ /*
++ * XRSTOR can fault if passed a corrupted data block. We handle this
++ * possibility, which may occur if the block was passed to us by control
++ * tools or through VCPUOP_initialise, by silently clearing the block.
++ */
++ asm volatile ( "1: .byte " REX_PREFIX "0x0f,0xae,0x2f\n"
++ ".section .fixup,\"ax\"\n"
++ "2: mov %5,%%ecx \n"
++ " xor %1,%1 \n"
++ " rep stosb \n"
++ " lea %2,%0 \n"
++ " mov %3,%1 \n"
++ " jmp 1b \n"
++ ".previous \n"
++ _ASM_EXTABLE(1b, 2b)
++ : "+&D" (ptr), "+&a" (lmask)
++ : "m" (*ptr), "g" (lmask), "d" (hmask),
++ "m" (xsave_cntxt_size)
++ : "ecx" );
+ }
+
+ bool_t xsave_enabled(const struct vcpu *v)
diff --git a/xsa54.patch b/xsa54.patch
new file mode 100644
index 0000000..83c8993
--- /dev/null
+++ b/xsa54.patch
@@ -0,0 +1,24 @@
+x86/xsave: properly check guest input to XSETBV
+
+Other than the HVM emulation path, the PV case so far failed to check
+that YMM state requires SSE state to be enabled, allowing for a #GP to
+occur upon passing the inputs to XSETBV inside the hypervisor.
+
+This is CVE-2013-2078 / XSA-54.
+
+Signed-off-by: Jan Beulich <jbeulich at suse.com>
+
+--- a/xen/arch/x86/traps.c
++++ b/xen/arch/x86/traps.c
+@@ -2205,6 +2205,11 @@ static int emulate_privileged_op(struct
+ if ( !(new_xfeature & XSTATE_FP) || (new_xfeature & ~xfeature_mask) )
+ goto fail;
+
++ /* YMM state takes SSE state as prerequisite. */
++ if ( (xfeature_mask & new_xfeature & XSTATE_YMM) &&
++ !(new_xfeature & XSTATE_SSE) )
++ goto fail;
++
+ v->arch.xcr0 = new_xfeature;
+ v->arch.xcr0_accum |= new_xfeature;
+ set_xcr0(new_xfeature);
diff --git a/xsa55-4.20001-libelf-abolish-libelf-relocate.c.patch b/xsa55-4.20001-libelf-abolish-libelf-relocate.c.patch
new file mode 100644
index 0000000..83070aa
--- /dev/null
+++ b/xsa55-4.20001-libelf-abolish-libelf-relocate.c.patch
@@ -0,0 +1,415 @@
+From d9d5d3ad927503fe89eece9b8e19eaab3e335e94 Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 24 May 2013 17:52:41 +0100
+Subject: [PATCH 01/16] 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).
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+Acked-by: Ian Campbell <ian.campbell at 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
+
diff --git a/xsa55-4.20002-libxc-introduce-xc_dom_seg_to_ptr_pages.patch b/xsa55-4.20002-libxc-introduce-xc_dom_seg_to_ptr_pages.patch
new file mode 100644
index 0000000..b4ed541
--- /dev/null
+++ b/xsa55-4.20002-libxc-introduce-xc_dom_seg_to_ptr_pages.patch
@@ -0,0 +1,50 @@
+From 8d895cda49f5334fc8248d2c802dc890cfbb03f0 Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 24 May 2013 17:52:41 +0100
+Subject: [PATCH 02/16] libxc: introduce xc_dom_seg_to_ptr_pages
+
+Provide a version of xc_dom_seg_to_ptr which returns the number of
+guest pages it has actually mapped. This is useful for callers who
+want to do range checking; we will use this later in this series.
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+Acked-by: Ian Campbell <ian.campbell at citrix.com>
+Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk at oracle.com>
+---
+ tools/libxc/xc_dom.h | 12 ++++++++++--
+ 1 files changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h
+index 6a72aa9..b74252f 100644
+--- a/tools/libxc/xc_dom.h
++++ b/tools/libxc/xc_dom.h
+@@ -278,16 +278,24 @@ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t first,
+ void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn);
+ void xc_dom_unmap_all(struct xc_dom_image *dom);
+
+-static inline void *xc_dom_seg_to_ptr(struct xc_dom_image *dom,
+- struct xc_dom_seg *seg)
++static inline void *xc_dom_seg_to_ptr_pages(struct xc_dom_image *dom,
++ struct xc_dom_seg *seg,
++ xen_pfn_t *pages_out)
+ {
+ xen_vaddr_t segsize = seg->vend - seg->vstart;
+ unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
+ xen_pfn_t pages = (segsize + page_size - 1) / page_size;
++ if (pages_out) *pages_out = pages;
+
+ return xc_dom_pfn_to_ptr(dom, seg->pfn, pages);
+ }
+
++static inline void *xc_dom_seg_to_ptr(struct xc_dom_image *dom,
++ struct xc_dom_seg *seg)
++{
++ return xc_dom_seg_to_ptr_pages(dom, seg, NULL);
++}
++
+ static inline void *xc_dom_vaddr_to_ptr(struct xc_dom_image *dom,
+ xen_vaddr_t vaddr)
+ {
+--
+1.7.2.5
+
diff --git a/xsa55-4.20003-libelf-add-struct-elf_binary-parameter-to-elf_load_i.patch b/xsa55-4.20003-libelf-add-struct-elf_binary-parameter-to-elf_load_i.patch
new file mode 100644
index 0000000..9d70887
--- /dev/null
+++ b/xsa55-4.20003-libelf-add-struct-elf_binary-parameter-to-elf_load_i.patch
@@ -0,0 +1,53 @@
+From a9cd2c35b3575f18de2bd86f7d5c18d418b05f38 Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 24 May 2013 17:52:41 +0100
+Subject: [PATCH 03/16] libelf: add `struct elf_binary*' parameter to elf_load_image
+
+The meat of this function is going to need a copy of the elf pointer,
+in forthcoming patches.
+
+No functional change in this patch.
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+Acked-by: Ian Campbell <ian.campbell at citrix.com>
+Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk at oracle.com>
+---
+ xen/common/libelf/libelf-loader.c | 8 +++++---
+ 1 files changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
+index ab58b8b..0559d88 100644
+--- a/xen/common/libelf/libelf-loader.c
++++ b/xen/common/libelf/libelf-loader.c
+@@ -108,7 +108,8 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
+ elf->verbose = verbose;
+ }
+
+-static int elf_load_image(void *dst, const void *src, uint64_t filesz, uint64_t memsz)
++static int elf_load_image(struct elf_binary *elf,
++ void *dst, const void *src, uint64_t filesz, uint64_t memsz)
+ {
+ memcpy(dst, src, filesz);
+ memset(dst + filesz, 0, memsz - filesz);
+@@ -122,7 +123,8 @@ void elf_set_verbose(struct elf_binary *elf)
+ elf->verbose = 1;
+ }
+
+-static int elf_load_image(void *dst, const void *src, uint64_t filesz, uint64_t memsz)
++static int elf_load_image(struct elf_binary *elf,
++ void *dst, const void *src, uint64_t filesz, uint64_t memsz)
+ {
+ int rc;
+ if ( filesz > ULONG_MAX || memsz > ULONG_MAX )
+@@ -279,7 +281,7 @@ int elf_load_binary(struct elf_binary *elf)
+ dest = elf_get_ptr(elf, paddr);
+ elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%p -> 0x%p\n",
+ __func__, i, dest, dest + filesz);
+- if ( elf_load_image(dest, elf->image + offset, filesz, memsz) != 0 )
++ if ( elf_load_image(elf, dest, elf->image + offset, filesz, memsz) != 0 )
+ return -1;
+ }
+
+--
+1.7.2.5
+
diff --git a/xsa55-4.20004-libelf-abolish-elf_sval-and-elf_access_signed.patch b/xsa55-4.20004-libelf-abolish-elf_sval-and-elf_access_signed.patch
new file mode 100644
index 0000000..41c0a22
--- /dev/null
+++ b/xsa55-4.20004-libelf-abolish-elf_sval-and-elf_access_signed.patch
@@ -0,0 +1,84 @@
+From 917217105a652c06bd2139fd34f0e6f03f4795d0 Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 24 May 2013 17:52:41 +0100
+Subject: [PATCH 04/16] libelf: abolish elf_sval and elf_access_signed
+
+These are not used anywhere.
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+Acked-by: Ian Campbell <ian.campbell at citrix.com>
+---
+ xen/common/libelf/libelf-tools.c | 28 ----------------------------
+ xen/include/xen/libelf.h | 11 -----------
+ 2 files changed, 0 insertions(+), 39 deletions(-)
+
+diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
+index cb97908..2f54142 100644
+--- a/xen/common/libelf/libelf-tools.c
++++ b/xen/common/libelf/libelf-tools.c
+@@ -48,34 +48,6 @@ uint64_t elf_access_unsigned(struct elf_binary * elf, const void *ptr,
+ }
+ }
+
+-int64_t elf_access_signed(struct elf_binary *elf, const void *ptr,
+- uint64_t offset, size_t size)
+-{
+- int need_swap = elf_swap(elf);
+- const int8_t *s8;
+- const int16_t *s16;
+- const int32_t *s32;
+- const int64_t *s64;
+-
+- switch ( size )
+- {
+- case 1:
+- s8 = ptr + offset;
+- return *s8;
+- case 2:
+- s16 = ptr + offset;
+- return need_swap ? bswap_16(*s16) : *s16;
+- case 4:
+- s32 = ptr + offset;
+- return need_swap ? bswap_32(*s32) : *s32;
+- case 8:
+- s64 = ptr + offset;
+- return need_swap ? bswap_64(*s64) : *s64;
+- default:
+- return 0;
+- }
+-}
+-
+ uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr)
+ {
+ int elf_round = (elf_64bit(elf) ? 8 : 4) - 1;
+diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
+index e8f6508..38e490c 100644
+--- a/xen/include/xen/libelf.h
++++ b/xen/include/xen/libelf.h
+@@ -136,23 +136,12 @@ struct elf_binary {
+ offsetof(typeof(*(str)),e32.elem), \
+ sizeof((str)->e32.elem)))
+
+-#define elf_sval(elf, str, elem) \
+- ((ELFCLASS64 == (elf)->class) \
+- ? elf_access_signed((elf), (str), \
+- offsetof(typeof(*(str)),e64.elem), \
+- sizeof((str)->e64.elem)) \
+- : elf_access_signed((elf), (str), \
+- offsetof(typeof(*(str)),e32.elem), \
+- sizeof((str)->e32.elem)))
+-
+ #define elf_size(elf, str) \
+ ((ELFCLASS64 == (elf)->class) \
+ ? sizeof((str)->e64) : sizeof((str)->e32))
+
+ uint64_t elf_access_unsigned(struct elf_binary *elf, const void *ptr,
+ uint64_t offset, size_t size);
+-int64_t elf_access_signed(struct elf_binary *elf, const void *ptr,
+- uint64_t offset, size_t size);
+
+ uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr);
+
+--
+1.7.2.5
+
diff --git a/xsa55-4.20005-libelf-move-include-of-asm-guest_access.h-to-top-of-.patch b/xsa55-4.20005-libelf-move-include-of-asm-guest_access.h-to-top-of-.patch
new file mode 100644
index 0000000..6bd383b
--- /dev/null
+++ b/xsa55-4.20005-libelf-move-include-of-asm-guest_access.h-to-top-of-.patch
@@ -0,0 +1,48 @@
+From c2a7f97c7100532aac72de2e242ae97dde3737a0 Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 24 May 2013 17:52:41 +0100
+Subject: [PATCH 05/16] libelf: move include of <asm/guest_access.h> to top of file
+
+libelf-loader.c #includes <asm/guest_access.h>, when being compiled
+for Xen. Currently it does this in the middle of the file.
+
+Move this #include to the top of the file, before libelf-private.h.
+This is necessary because in forthcoming patches we will introduce
+private #defines of memcpy etc. which would interfere with definitions
+in headers #included from guest_access.h.
+
+No semantic or functional change in this patch.
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+Acked-by: Ian Campbell <ian.campbell at citrix.com>
+Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk at oracle.com>
+---
+ xen/common/libelf/libelf-loader.c | 5 ++++-
+ 1 files changed, 4 insertions(+), 1 deletions(-)
+
+diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
+index 0559d88..ec0706b 100644
+--- a/xen/common/libelf/libelf-loader.c
++++ b/xen/common/libelf/libelf-loader.c
+@@ -16,6 +16,10 @@
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
++#ifdef __XEN__
++#include <asm/guest_access.h>
++#endif
++
+ #include "libelf-private.h"
+
+ /* ------------------------------------------------------------------------ */
+@@ -116,7 +120,6 @@ static int elf_load_image(struct elf_binary *elf,
+ return 0;
+ }
+ #else
+-#include <asm/guest_access.h>
+
+ void elf_set_verbose(struct elf_binary *elf)
+ {
+--
+1.7.2.5
+
diff --git a/xsa55-4.20006-libelf-xc_dom_load_elf_symtab-Do-not-use-syms-uninit.patch b/xsa55-4.20006-libelf-xc_dom_load_elf_symtab-Do-not-use-syms-uninit.patch
new file mode 100644
index 0000000..f5a655e
--- /dev/null
+++ b/xsa55-4.20006-libelf-xc_dom_load_elf_symtab-Do-not-use-syms-uninit.patch
@@ -0,0 +1,41 @@
+From 9ba416dd299ee3ad62dda7de3411210c78ee4ebc Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 24 May 2013 17:52:42 +0100
+Subject: [PATCH 06/16] libelf/xc_dom_load_elf_symtab: Do not use "syms" uninitialised
+
+xc_dom_load_elf_symtab (with load==0) calls elf_round_up, but it
+mistakenly used the uninitialised variable "syms" when calculating
+dom->bsd_symtab_start. This should be a reference to "elf".
+
+This change might have the effect of rounding the value differently.
+Previously if the uninitialised value (a single byte on the stack) was
+ELFCLASS64 (ie, 2), the alignment would be to 8 bytes, otherwise to 4.
+
+However, the value is calculated from dom->kernel_seg.vend so this
+could only make a difference if that value wasn't already aligned to 8
+bytes.
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+Acked-by: Ian Campbell <ian.campbell at citrix.com>
+
+v2: Split this change into its own patch for proper review.
+---
+ tools/libxc/xc_dom_elfloader.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
+index 2e69559..8bd59ca 100644
+--- a/tools/libxc/xc_dom_elfloader.c
++++ b/tools/libxc/xc_dom_elfloader.c
+@@ -143,7 +143,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+ hdr = xc_dom_malloc(dom, size);
+ if ( hdr == NULL )
+ return 0;
+- dom->bsd_symtab_start = elf_round_up(&syms, dom->kernel_seg.vend);
++ dom->bsd_symtab_start = elf_round_up(elf, dom->kernel_seg.vend);
+ }
+
+ memcpy(hdr + sizeof(int),
+--
+1.7.2.5
+
diff --git a/xsa55-4.20007-libelf-introduce-macros-for-memory-access-and-pointe.patch b/xsa55-4.20007-libelf-introduce-macros-for-memory-access-and-pointe.patch
new file mode 100644
index 0000000..335880f
--- /dev/null
+++ b/xsa55-4.20007-libelf-introduce-macros-for-memory-access-and-pointe.patch
@@ -0,0 +1,1208 @@
+From 7ea097951208852fc01645a9fceec848212aa52c Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 24 May 2013 17:52:42 +0100
+Subject: [PATCH 07/16] libelf: introduce macros for memory access and pointer handling
+
+We introduce a collection of macros which abstract away all the
+pointer arithmetic and dereferences used for accessing the input ELF
+and the output area(s). We use the new macros everywhere.
+
+For now, these macros are semantically identical to the code they
+replace, so this patch has no functional change.
+
+elf_is_elfbinary is an exception: since it doesn't take an elf*, we
+need to handle it differently. In a future patch we will change it to
+take, and check, a length parameter. For now we just mark it with a
+fixme.
+
+Differences in the 4.2 backport: ELF_OBSOLETE_VOIDP_CAST includes a
+cast to uintptr_t to suppress warnings about conversions between
+integers and differently-sized pointers. In elf_load_binary we
+include one cast to ELF_PTRVAL_VOID to narrow a 64-bit value to
+32-bit on x86_32.
+
+That this patch has no functional change can be verified as follows:
+
+ 0. Copy the scripts "comparison-generate" and "function-filter"
+ out of this commit message.
+ 1. Check out the tree before this patch.
+ 2. Run the script ../comparison-generate .... ../before
+ 3. Check out the tree after this patch.
+ 4. Run the script ../comparison-generate .... ../after
+ 5. diff --exclude=\*.[soi] -ruN before/ after/ |less
+
+Expect these differences:
+ * stubdom/zlib-x86_64/ztest*.s2
+ The filename of this test file apparently contains the pid.
+ * xen/common/version.s2
+ The xen build timestamp appears in two diff hunks.
+
+Verification that this is all that's needed:
+ In a completely built xen.git,
+ find * -name .*.d -type f | xargs grep -l libelf\.h
+ Expect results in:
+ xen/arch/x86: Checked above.
+ tools/libxc: Checked above.
+ tools/xcutils/readnotes: Checked above.
+ tools/xenstore: Checked above.
+ xen/common/libelf:
+ This is the build for the hypervisor; checked in B above.
+ stubdom:
+ We have one stubdom which reads ELFs using our libelf,
+ pvgrub, which is checked above.
+
+I have not done this verification for ARM.
+
+-8<- comparison-generate -8<-
+ #!/bin/bash
+ # usage:
+ # cd xen.git
+ # .../comparison-generate OUR-CONFIG BUILD-RUNE-PREFIX ../before|../after
+ # eg:
+ # .../comparison-generate ~/work/.config 'schroot -pc64 --' ../before
+ set -ex
+
+ test $# = 3 || need-exactly-three-arguments
+
+ our_config=$1
+ build_rune_prefix=$2
+ result_dir=$3
+
+ git-clean -x -d -f
+
+ cp "$our_config" .
+
+ cat <<END >>.config
+ debug_symbols=n
+ CFLAGS += -save-temps
+ END
+
+ perl -i~ -pe 's/ -g / -g0 / if m/^CFLAGS/' xen/Rules.mk
+
+ if [ -f ./configure ]; then
+ $build_rune_prefix ./configure
+ fi
+
+ $build_rune_prefix make -C xen
+ $build_rune_prefix make -C tools/include
+ $build_rune_prefix make -C stubdom grub
+ $build_rune_prefix make -C tools/libxc
+ $build_rune_prefix make -C tools/xenstore
+ $build_rune_prefix make -C tools/xcutils
+
+ rm -rf "$result_dir"
+ mkdir "$result_dir"
+
+ set +x
+ for f in `find xen tools stubdom -name \*.[soi]`; do
+ mkdir -p "$result_dir"/`dirname $f`
+ cp $f "$result_dir"/${f}
+ case $f in
+ *.s)
+ ../function-filter <$f >"$result_dir"/${f}2
+ ;;
+ esac
+ done
+
+ echo ok.
+-8<-
+
+-8<- function-filter -8<-
+ #!/usr/bin/perl -w
+ # for f in *.s; do ~/work/function-filter <$f >${f}2; done
+ use strict;
+ our @lines;
+ my $sedderybody = "sub seddery () {\n";
+ while (<>) {
+ push @lines, $_;
+ if (m/^(__FUNCTION__|__func__)\.(\d+)\:/) {
+ $sedderybody .= " s/\\b$1\\.$2\\b/__XSA55MANGLED__$1.$./g;\n";
+ }
+ }
+ $sedderybody .= "}\n1;\n";
+ eval $sedderybody or die $@;
+ foreach (@lines) {
+ seddery();
+ print or die $!;
+ }
+-8<-
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+
+v3.1:
+ Change elf_store_field to verify correctly on 32-bit i386.
+
+v2 Acked-by: Ian Campbell <ian.campbell at citrix.com>
+v2 Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk at oracle.com>
+
+v2: Use Xen style for multi-line comments.
+ Postpone changes to readnotes.c:print_l1_mfn_valid_note.
+ Much improved verification instructions with new script.
+ Fixed commit message subject.
+---
+ tools/libxc/xc_dom_elfloader.c | 30 +++---
+ tools/libxc/xc_hvm_build_x86.c | 2 +-
+ tools/xcutils/readnotes.c | 26 +++---
+ xen/common/libelf/libelf-dominfo.c | 51 +++++-----
+ xen/common/libelf/libelf-loader.c | 84 +++++++++--------
+ xen/common/libelf/libelf-tools.c | 94 +++++++++---------
+ xen/include/xen/libelf.h | 188 +++++++++++++++++++++++++++++++-----
+ 7 files changed, 312 insertions(+), 163 deletions(-)
+
+diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
+index 8bd59ca..e481649 100644
+--- a/tools/libxc/xc_dom_elfloader.c
++++ b/tools/libxc/xc_dom_elfloader.c
+@@ -115,9 +115,9 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+ struct elf_binary *elf, int load)
+ {
+ struct elf_binary syms;
+- const elf_shdr *shdr, *shdr2;
++ ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr; ELF_HANDLE_DECL(elf_shdr) shdr2;
+ xen_vaddr_t symtab, maxaddr;
+- char *hdr;
++ ELF_PTRVAL_CHAR hdr;
+ size_t size;
+ int h, count, type, i, tables = 0;
+
+@@ -146,11 +146,11 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+ dom->bsd_symtab_start = elf_round_up(elf, dom->kernel_seg.vend);
+ }
+
+- memcpy(hdr + sizeof(int),
+- elf->image,
++ elf_memcpy_safe(elf, hdr + sizeof(int),
++ ELF_IMAGE_BASE(elf),
+ elf_size(elf, elf->ehdr));
+- memcpy(hdr + sizeof(int) + elf_size(elf, elf->ehdr),
+- elf->image + elf_uval(elf, elf->ehdr, e_shoff),
++ elf_memcpy_safe(elf, hdr + sizeof(int) + elf_size(elf, elf->ehdr),
++ ELF_IMAGE_BASE(elf) + elf_uval(elf, elf->ehdr, e_shoff),
+ elf_shdr_count(elf) * elf_size(elf, shdr));
+ if ( elf_64bit(elf) )
+ {
+@@ -188,7 +188,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+ count = elf_shdr_count(&syms);
+ for ( h = 0; h < count; h++ )
+ {
+- shdr = elf_shdr_by_index(&syms, h);
++ shdr = ELF_OBSOLETE_VOIDP_CAST elf_shdr_by_index(&syms, h);
+ type = elf_uval(&syms, shdr, sh_type);
+ if ( type == SHT_STRTAB )
+ {
+@@ -204,9 +204,9 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+ if ( i == count )
+ {
+ if ( elf_64bit(&syms) )
+- *(Elf64_Off*)(&shdr->e64.sh_offset) = 0;
++ elf_store_field(elf, shdr, e64.sh_offset, 0);
+ else
+- *(Elf32_Off*)(&shdr->e32.sh_offset) = 0;
++ elf_store_field(elf, shdr, e32.sh_offset, 0);
+ continue;
+ }
+ }
+@@ -215,9 +215,9 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+ {
+ /* Mangled to be based on ELF header location. */
+ if ( elf_64bit(&syms) )
+- *(Elf64_Off*)(&shdr->e64.sh_offset) = maxaddr - symtab;
++ elf_store_field(elf, shdr, e64.sh_offset, maxaddr - symtab);
+ else
+- *(Elf32_Off*)(&shdr->e32.sh_offset) = maxaddr - symtab;
++ elf_store_field(elf, shdr, e32.sh_offset, maxaddr - symtab);
+ size = elf_uval(&syms, shdr, sh_size);
+ maxaddr = elf_round_up(&syms, maxaddr + size);
+ tables++;
+@@ -229,7 +229,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+ if ( load )
+ {
+ shdr2 = elf_shdr_by_index(elf, h);
+- memcpy((void*)elf_section_start(&syms, shdr),
++ elf_memcpy_safe(elf, ELF_OBSOLETE_VOIDP_CAST elf_section_start(&syms, shdr),
+ elf_section_start(elf, shdr2),
+ size);
+ }
+@@ -237,9 +237,9 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+
+ /* Name is NULL. */
+ if ( elf_64bit(&syms) )
+- *(Elf64_Word*)(&shdr->e64.sh_name) = 0;
++ elf_store_field(elf, shdr, e64.sh_name, 0);
+ else
+- *(Elf32_Word*)(&shdr->e32.sh_name) = 0;
++ elf_store_field(elf, shdr, e32.sh_name, 0);
+ }
+
+ if ( tables == 0 )
+@@ -274,7 +274,7 @@ static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
+ }
+
+ /* Find the section-header strings table. */
+- if ( elf->sec_strtab == NULL )
++ if ( ELF_PTRVAL_INVALID(elf->sec_strtab) )
+ {
+ xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: ELF image"
+ " has no shstrtab", __FUNCTION__);
+diff --git a/tools/libxc/xc_hvm_build_x86.c b/tools/libxc/xc_hvm_build_x86.c
+index cf5d7fb..15b603d 100644
+--- a/tools/libxc/xc_hvm_build_x86.c
++++ b/tools/libxc/xc_hvm_build_x86.c
+@@ -110,7 +110,7 @@ static int loadelfimage(
+ if ( elf->dest == NULL )
+ goto err;
+
+- elf->dest += elf->pstart & (PAGE_SIZE - 1);
++ ELF_ADVANCE_DEST(elf, elf->pstart & (PAGE_SIZE - 1));
+
+ /* Load the initial elf image. */
+ rc = elf_load_binary(elf);
+diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
+index c926186..2af047d 100644
+--- a/tools/xcutils/readnotes.c
++++ b/tools/xcutils/readnotes.c
+@@ -61,13 +61,13 @@ struct setup_header {
+ } __attribute__((packed));
+
+ static void print_string_note(const char *prefix, struct elf_binary *elf,
+- const elf_note *note)
++ ELF_HANDLE_DECL(elf_note) note)
+ {
+ printf("%s: %s\n", prefix, (char*)elf_note_desc(elf, note));
+ }
+
+ static void print_numeric_note(const char *prefix, struct elf_binary *elf,
+- const elf_note *note)
++ ELF_HANDLE_DECL(elf_note) note)
+ {
+ uint64_t value = elf_note_numeric(elf, note);
+ int descsz = elf_uval(elf, note, descsz);
+@@ -98,12 +98,12 @@ static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf,
+
+ }
+
+-static int print_notes(struct elf_binary *elf, const elf_note *start, const elf_note *end)
++static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start, ELF_HANDLE_DECL(elf_note) end)
+ {
+- const elf_note *note;
++ ELF_HANDLE_DECL(elf_note) note;
+ int notes_found = 0;
+
+- for ( note = start; note < end; note = elf_note_next(elf, note) )
++ for ( note = start; ELF_HANDLE_PTRVAL(note) < ELF_HANDLE_PTRVAL(end); note = elf_note_next(elf, note) )
+ {
+ if (0 != strcmp(elf_note_name(elf, note), "Xen"))
+ continue;
+@@ -170,7 +170,7 @@ int main(int argc, char **argv)
+ void *image,*tmp;
+ struct stat st;
+ struct elf_binary elf;
+- const elf_shdr *shdr;
++ ELF_HANDLE_DECL(elf_shdr) shdr;
+ int notes_found = 0;
+
+ struct setup_header *hdr;
+@@ -257,7 +257,7 @@ int main(int argc, char **argv)
+ count = elf_phdr_count(&elf);
+ for ( h=0; h < count; h++)
+ {
+- const elf_phdr *phdr;
++ ELF_HANDLE_DECL(elf_phdr) phdr;
+ phdr = elf_phdr_by_index(&elf, h);
+ if (elf_uval(&elf, phdr, p_type) != PT_NOTE)
+ continue;
+@@ -269,8 +269,8 @@ int main(int argc, char **argv)
+ continue;
+
+ notes_found = print_notes(&elf,
+- elf_segment_start(&elf, phdr),
+- elf_segment_end(&elf, phdr));
++ ELF_MAKE_HANDLE(elf_note, elf_segment_start(&elf, phdr)),
++ ELF_MAKE_HANDLE(elf_note, elf_segment_end(&elf, phdr)));
+ }
+
+ if ( notes_found == 0 )
+@@ -278,13 +278,13 @@ int main(int argc, char **argv)
+ count = elf_shdr_count(&elf);
+ for ( h=0; h < count; h++)
+ {
+- const elf_shdr *shdr;
++ ELF_HANDLE_DECL(elf_shdr) shdr;
+ shdr = elf_shdr_by_index(&elf, h);
+ if (elf_uval(&elf, shdr, sh_type) != SHT_NOTE)
+ continue;
+ notes_found = print_notes(&elf,
+- elf_section_start(&elf, shdr),
+- elf_section_end(&elf, shdr));
++ ELF_MAKE_HANDLE(elf_note, elf_section_start(&elf, shdr)),
++ ELF_MAKE_HANDLE(elf_note, elf_section_end(&elf, shdr)));
+ if ( notes_found )
+ fprintf(stderr, "using notes from SHT_NOTE section\n");
+
+@@ -292,7 +292,7 @@ int main(int argc, char **argv)
+ }
+
+ shdr = elf_shdr_by_name(&elf, "__xen_guest");
+- if (shdr)
++ if (ELF_HANDLE_VALID(shdr))
+ printf("__xen_guest: %s\n", (char*)elf_section_start(&elf, shdr));
+
+ return 0;
+diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
+index 523837f..7140d59 100644
+--- a/xen/common/libelf/libelf-dominfo.c
++++ b/xen/common/libelf/libelf-dominfo.c
+@@ -44,7 +44,7 @@ int elf_xen_parse_features(const char *features,
+
+ for ( pos = 0; features[pos] != '\0'; pos += len )
+ {
+- memset(feature, 0, sizeof(feature));
++ elf_memset_unchecked(feature, 0, sizeof(feature));
+ for ( len = 0;; len++ )
+ {
+ if ( len >= sizeof(feature)-1 )
+@@ -96,7 +96,7 @@ int elf_xen_parse_features(const char *features,
+
+ int elf_xen_parse_note(struct elf_binary *elf,
+ struct elf_dom_parms *parms,
+- const elf_note *note)
++ ELF_HANDLE_DECL(elf_note) note)
+ {
+ /* *INDENT-OFF* */
+ static const struct {
+@@ -215,15 +215,16 @@ int elf_xen_parse_note(struct elf_binary *elf,
+
+ static int elf_xen_parse_notes(struct elf_binary *elf,
+ struct elf_dom_parms *parms,
+- const void *start, const void *end)
++ ELF_PTRVAL_CONST_VOID start,
++ ELF_PTRVAL_CONST_VOID end)
+ {
+ int xen_elfnotes = 0;
+- const elf_note *note;
++ ELF_HANDLE_DECL(elf_note) note;
+
+ parms->elf_note_start = start;
+ parms->elf_note_end = end;
+- for ( note = parms->elf_note_start;
+- (void *)note < parms->elf_note_end;
++ for ( note = ELF_MAKE_HANDLE(elf_note, parms->elf_note_start);
++ ELF_HANDLE_PTRVAL(note) < parms->elf_note_end;
+ note = elf_note_next(elf, note) )
+ {
+ if ( strcmp(elf_note_name(elf, note), "Xen") )
+@@ -241,45 +242,46 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
+ int elf_xen_parse_guest_info(struct elf_binary *elf,
+ struct elf_dom_parms *parms)
+ {
+- const char *h;
++ ELF_PTRVAL_CONST_CHAR h;
+ char name[32], value[128];
+ int len;
+
+ h = parms->guest_info;
+- while ( *h )
++#define STAR(h) (*(h))
++ while ( STAR(h) )
+ {
+- memset(name, 0, sizeof(name));
+- memset(value, 0, sizeof(value));
++ elf_memset_unchecked(name, 0, sizeof(name));
++ elf_memset_unchecked(value, 0, sizeof(value));
+ for ( len = 0;; len++, h++ )
+ {
+ if ( len >= sizeof(name)-1 )
+ break;
+- if ( *h == '\0' )
++ if ( STAR(h) == '\0' )
+ break;
+- if ( *h == ',' )
++ if ( STAR(h) == ',' )
+ {
+ h++;
+ break;
+ }
+- if ( *h == '=' )
++ if ( STAR(h) == '=' )
+ {
+ h++;
+ for ( len = 0;; len++, h++ )
+ {
+ if ( len >= sizeof(value)-1 )
+ break;
+- if ( *h == '\0' )
++ if ( STAR(h) == '\0' )
+ break;
+- if ( *h == ',' )
++ if ( STAR(h) == ',' )
+ {
+ h++;
+ break;
+ }
+- value[len] = *h;
++ value[len] = STAR(h);
+ }
+ break;
+ }
+- name[len] = *h;
++ name[len] = STAR(h);
+ }
+ elf_msg(elf, "%s: %s=\"%s\"\n", __FUNCTION__, name, value);
+
+@@ -328,7 +330,8 @@ int elf_xen_parse_guest_info(struct elf_binary *elf,
+ static int elf_xen_note_check(struct elf_binary *elf,
+ struct elf_dom_parms *parms)
+ {
+- if ( (parms->elf_note_start == NULL) && (parms->guest_info == NULL) )
++ if ( (ELF_PTRVAL_INVALID(parms->elf_note_start)) &&
++ (ELF_PTRVAL_INVALID(parms->guest_info)) )
+ {
+ int machine = elf_uval(elf, elf->ehdr, e_machine);
+ if ( (machine == EM_386) || (machine == EM_X86_64) )
+@@ -457,12 +460,12 @@ static int elf_xen_addr_calc_check(struct elf_binary *elf,
+ int elf_xen_parse(struct elf_binary *elf,
+ struct elf_dom_parms *parms)
+ {
+- const elf_shdr *shdr;
+- const elf_phdr *phdr;
++ ELF_HANDLE_DECL(elf_shdr) shdr;
++ ELF_HANDLE_DECL(elf_phdr) phdr;
+ int xen_elfnotes = 0;
+ int i, count, rc;
+
+- memset(parms, 0, sizeof(*parms));
++ elf_memset_unchecked(parms, 0, sizeof(*parms));
+ parms->virt_base = UNSET_ADDR;
+ parms->virt_entry = UNSET_ADDR;
+ parms->virt_hypercall = UNSET_ADDR;
+@@ -532,11 +535,11 @@ int elf_xen_parse(struct elf_binary *elf,
+ for ( i = 0; i < count; i++ )
+ {
+ shdr = elf_shdr_by_name(elf, "__xen_guest");
+- if ( shdr )
++ if ( ELF_HANDLE_VALID(shdr) )
+ {
+ parms->guest_info = elf_section_start(elf, shdr);
+- parms->elf_note_start = NULL;
+- parms->elf_note_end = NULL;
++ parms->elf_note_start = ELF_INVALID_PTRVAL;
++ parms->elf_note_end = ELF_INVALID_PTRVAL;
+ elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__,
+ parms->guest_info);
+ elf_xen_parse_guest_info(elf, parms);
+diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
+index ec0706b..0fef84c 100644
+--- a/xen/common/libelf/libelf-loader.c
++++ b/xen/common/libelf/libelf-loader.c
+@@ -26,7 +26,7 @@
+
+ int elf_init(struct elf_binary *elf, const char *image, size_t size)
+ {
+- const elf_shdr *shdr;
++ ELF_HANDLE_DECL(elf_shdr) shdr;
+ uint64_t i, count, section, offset;
+
+ if ( !elf_is_elfbinary(image) )
+@@ -35,7 +35,7 @@ int elf_init(struct elf_binary *elf, const char *image, size_t size)
+ return -1;
+ }
+
+- memset(elf, 0, sizeof(*elf));
++ elf_memset_unchecked(elf, 0, sizeof(*elf));
+ elf->image = image;
+ elf->size = size;
+ elf->ehdr = (elf_ehdr *)image;
+@@ -65,7 +65,7 @@ int elf_init(struct elf_binary *elf, const char *image, size_t size)
+ /* Find section string table. */
+ section = elf_uval(elf, elf->ehdr, e_shstrndx);
+ shdr = elf_shdr_by_index(elf, section);
+- if ( shdr != NULL )
++ if ( ELF_HANDLE_VALID(shdr) )
+ elf->sec_strtab = elf_section_start(elf, shdr);
+
+ /* Find symbol table and symbol string table. */
+@@ -77,9 +77,9 @@ int elf_init(struct elf_binary *elf, const char *image, size_t size)
+ continue;
+ elf->sym_tab = shdr;
+ shdr = elf_shdr_by_index(elf, elf_uval(elf, shdr, sh_link));
+- if ( shdr == NULL )
++ if ( !ELF_HANDLE_VALID(shdr) )
+ {
+- elf->sym_tab = NULL;
++ elf->sym_tab = ELF_INVALID_HANDLE(elf_shdr);
+ continue;
+ }
+ elf->sym_strtab = elf_section_start(elf, shdr);
+@@ -113,10 +113,11 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
+ }
+
+ static int elf_load_image(struct elf_binary *elf,
+- void *dst, const void *src, uint64_t filesz, uint64_t memsz)
++ ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src,
++ uint64_t filesz, uint64_t memsz)
+ {
+- memcpy(dst, src, filesz);
+- memset(dst + filesz, 0, memsz - filesz);
++ elf_memcpy_safe(elf, dst, src, filesz);
++ elf_memset_safe(elf, dst + filesz, 0, memsz - filesz);
+ return 0;
+ }
+ #else
+@@ -126,16 +127,17 @@ void elf_set_verbose(struct elf_binary *elf)
+ elf->verbose = 1;
+ }
+
+-static int elf_load_image(struct elf_binary *elf,
+- void *dst, const void *src, uint64_t filesz, uint64_t memsz)
++static int elf_load_image(struct elf_binary *elf, ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src, uint64_t filesz, uint64_t memsz)
+ {
+ int rc;
+ if ( filesz > ULONG_MAX || memsz > ULONG_MAX )
+ return -1;
+- rc = raw_copy_to_guest(dst, src, filesz);
++ /* We trust the dom0 kernel image completely, so we don't care
++ * about overruns etc. here. */
++ rc = raw_copy_to_guest(ELF_UNSAFE_PTR(dst), ELF_UNSAFE_PTR(src), filesz);
+ if ( rc != 0 )
+ return -1;
+- rc = raw_clear_guest(dst + filesz, memsz - filesz);
++ rc = raw_clear_guest(ELF_UNSAFE_PTR(dst + filesz), memsz - filesz);
+ if ( rc != 0 )
+ return -1;
+ return 0;
+@@ -146,10 +148,10 @@ static int elf_load_image(struct elf_binary *elf,
+ void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart)
+ {
+ uint64_t sz;
+- const elf_shdr *shdr;
++ ELF_HANDLE_DECL(elf_shdr) shdr;
+ int i, type;
+
+- if ( !elf->sym_tab )
++ if ( !ELF_HANDLE_VALID(elf->sym_tab) )
+ return;
+
+ pstart = elf_round_up(elf, pstart);
+@@ -166,7 +168,7 @@ void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart)
+ for ( i = 0; i < elf_shdr_count(elf); i++ )
+ {
+ shdr = elf_shdr_by_index(elf, i);
+- type = elf_uval(elf, (elf_shdr *)shdr, sh_type);
++ type = elf_uval(elf, shdr, sh_type);
+ if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) )
+ sz = elf_round_up(elf, sz + elf_uval(elf, shdr, sh_size));
+ }
+@@ -177,10 +179,12 @@ void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart)
+
+ static void elf_load_bsdsyms(struct elf_binary *elf)
+ {
+- elf_ehdr *sym_ehdr;
++ ELF_HANDLE_DECL_NONCONST(elf_ehdr) sym_ehdr;
+ unsigned long sz;
+- char *maxva, *symbase, *symtab_addr;
+- elf_shdr *shdr;
++ ELF_PTRVAL_VOID maxva;
++ ELF_PTRVAL_VOID symbase;
++ ELF_PTRVAL_VOID symtab_addr;
++ ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr;
+ int i, type;
+
+ if ( !elf->bsd_symtab_pstart )
+@@ -189,18 +193,18 @@ static void elf_load_bsdsyms(struct elf_binary *elf)
+ #define elf_hdr_elm(_elf, _hdr, _elm, _val) \
+ do { \
+ if ( elf_64bit(_elf) ) \
+- (_hdr)->e64._elm = _val; \
++ elf_store_field(_elf, _hdr, e64._elm, _val); \
+ else \
+- (_hdr)->e32._elm = _val; \
++ elf_store_field(_elf, _hdr, e32._elm, _val); \
+ } while ( 0 )
+
+ symbase = elf_get_ptr(elf, elf->bsd_symtab_pstart);
+ symtab_addr = maxva = symbase + sizeof(uint32_t);
+
+ /* Set up Elf header. */
+- sym_ehdr = (elf_ehdr *)symtab_addr;
++ sym_ehdr = ELF_MAKE_HANDLE(elf_ehdr, symtab_addr);
+ sz = elf_uval(elf, elf->ehdr, e_ehsize);
+- memcpy(sym_ehdr, elf->ehdr, sz);
++ elf_memcpy_safe(elf, ELF_HANDLE_PTRVAL(sym_ehdr), ELF_HANDLE_PTRVAL(elf->ehdr), sz);
+ maxva += sz; /* no round up */
+
+ elf_hdr_elm(elf, sym_ehdr, e_phoff, 0);
+@@ -209,37 +213,39 @@ do { \
+ elf_hdr_elm(elf, sym_ehdr, e_phnum, 0);
+
+ /* Copy Elf section headers. */
+- shdr = (elf_shdr *)maxva;
++ shdr = ELF_MAKE_HANDLE(elf_shdr, maxva);
+ sz = elf_shdr_count(elf) * elf_uval(elf, elf->ehdr, e_shentsize);
+- memcpy(shdr, elf->image + elf_uval(elf, elf->ehdr, e_shoff), sz);
+- maxva = (char *)(long)elf_round_up(elf, (long)maxva + sz);
++ elf_memcpy_safe(elf, ELF_HANDLE_PTRVAL(shdr),
++ ELF_IMAGE_BASE(elf) + elf_uval(elf, elf->ehdr, e_shoff),
++ sz);
++ maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (long)maxva + sz);
+
+ for ( i = 0; i < elf_shdr_count(elf); i++ )
+ {
+ type = elf_uval(elf, shdr, sh_type);
+ if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) )
+ {
+- elf_msg(elf, "%s: shdr %i at 0x%p -> 0x%p\n", __func__, i,
++ elf_msg(elf, "%s: shdr %i at 0x%"ELF_PRPTRVAL" -> 0x%"ELF_PRPTRVAL"\n", __func__, i,
+ elf_section_start(elf, shdr), maxva);
+ sz = elf_uval(elf, shdr, sh_size);
+- memcpy(maxva, elf_section_start(elf, shdr), sz);
++ elf_memcpy_safe(elf, maxva, elf_section_start(elf, shdr), sz);
+ /* Mangled to be based on ELF header location. */
+ elf_hdr_elm(elf, shdr, sh_offset, maxva - symtab_addr);
+- maxva = (char *)(long)elf_round_up(elf, (long)maxva + sz);
++ maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (long)maxva + sz);
+ }
+- shdr = (elf_shdr *)((long)shdr +
++ shdr = ELF_MAKE_HANDLE(elf_shdr, ELF_HANDLE_PTRVAL(shdr) +
+ (long)elf_uval(elf, elf->ehdr, e_shentsize));
+ }
+
+ /* Write down the actual sym size. */
+- *(uint32_t *)symbase = maxva - symtab_addr;
++ elf_store_val(elf, uint32_t, symbase, maxva - symtab_addr);
+
+ #undef elf_ehdr_elm
+ }
+
+ void elf_parse_binary(struct elf_binary *elf)
+ {
+- const elf_phdr *phdr;
++ ELF_HANDLE_DECL(elf_phdr) phdr;
+ uint64_t low = -1;
+ uint64_t high = 0;
+ uint64_t i, count, paddr, memsz;
+@@ -267,9 +273,9 @@ void elf_parse_binary(struct elf_binary *elf)
+
+ int elf_load_binary(struct elf_binary *elf)
+ {
+- const elf_phdr *phdr;
++ ELF_HANDLE_DECL(elf_phdr) phdr;
+ uint64_t i, count, paddr, offset, filesz, memsz;
+- char *dest;
++ ELF_PTRVAL_VOID dest;
+
+ count = elf_uval(elf, elf->ehdr, e_phnum);
+ for ( i = 0; i < count; i++ )
+@@ -282,9 +288,9 @@ int elf_load_binary(struct elf_binary *elf)
+ filesz = elf_uval(elf, phdr, p_filesz);
+ memsz = elf_uval(elf, phdr, p_memsz);
+ dest = elf_get_ptr(elf, paddr);
+- elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%p -> 0x%p\n",
+- __func__, i, dest, dest + filesz);
+- if ( elf_load_image(elf, dest, elf->image + offset, filesz, memsz) != 0 )
++ elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%"ELF_PRPTRVAL" -> 0x%"ELF_PRPTRVAL"\n",
++ __func__, i, dest, (ELF_PTRVAL_VOID)(dest + filesz));
++ if ( elf_load_image(elf, dest, ELF_IMAGE_BASE(elf) + offset, filesz, memsz) != 0 )
+ return -1;
+ }
+
+@@ -292,18 +298,18 @@ int elf_load_binary(struct elf_binary *elf)
+ return 0;
+ }
+
+-void *elf_get_ptr(struct elf_binary *elf, unsigned long addr)
++ELF_PTRVAL_VOID elf_get_ptr(struct elf_binary *elf, unsigned long addr)
+ {
+ return elf->dest + addr - elf->pstart;
+ }
+
+ uint64_t elf_lookup_addr(struct elf_binary * elf, const char *symbol)
+ {
+- const elf_sym *sym;
++ ELF_HANDLE_DECL(elf_sym) sym;
+ uint64_t value;
+
+ sym = elf_sym_by_name(elf, symbol);
+- if ( sym == NULL )
++ if ( !ELF_HANDLE_VALID(sym) )
+ {
+ elf_err(elf, "%s: not found: %s\n", __FUNCTION__, symbol);
+ return -1;
+diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
+index 2f54142..f1fd886 100644
+--- a/xen/common/libelf/libelf-tools.c
++++ b/xen/common/libelf/libelf-tools.c
+@@ -67,10 +67,10 @@ int elf_phdr_count(struct elf_binary *elf)
+ return elf_uval(elf, elf->ehdr, e_phnum);
+ }
+
+-const elf_shdr *elf_shdr_by_name(struct elf_binary *elf, const char *name)
++ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *name)
+ {
+ uint64_t count = elf_shdr_count(elf);
+- const elf_shdr *shdr;
++ ELF_HANDLE_DECL(elf_shdr) shdr;
+ const char *sname;
+ int i;
+
+@@ -81,76 +81,80 @@ const elf_shdr *elf_shdr_by_name(struct elf_binary *elf, const char *name)
+ if ( sname && !strcmp(sname, name) )
+ return shdr;
+ }
+- return NULL;
++ return ELF_INVALID_HANDLE(elf_shdr);
+ }
+
+-const elf_shdr *elf_shdr_by_index(struct elf_binary *elf, int index)
++ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index)
+ {
+ uint64_t count = elf_shdr_count(elf);
+- const void *ptr;
++ ELF_PTRVAL_CONST_VOID ptr;
+
+ if ( index >= count )
+- return NULL;
++ return ELF_INVALID_HANDLE(elf_shdr);
+
+- ptr = (elf->image
++ ptr = (ELF_IMAGE_BASE(elf)
+ + elf_uval(elf, elf->ehdr, e_shoff)
+ + elf_uval(elf, elf->ehdr, e_shentsize) * index);
+- return ptr;
++ return ELF_MAKE_HANDLE(elf_shdr, ptr);
+ }
+
+-const elf_phdr *elf_phdr_by_index(struct elf_binary *elf, int index)
++ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, int index)
+ {
+ uint64_t count = elf_uval(elf, elf->ehdr, e_phnum);
+- const void *ptr;
++ ELF_PTRVAL_CONST_VOID ptr;
+
+ if ( index >= count )
+- return NULL;
++ return ELF_INVALID_HANDLE(elf_phdr);
+
+- ptr = (elf->image
++ ptr = (ELF_IMAGE_BASE(elf)
+ + elf_uval(elf, elf->ehdr, e_phoff)
+ + elf_uval(elf, elf->ehdr, e_phentsize) * index);
+- return ptr;
++ return ELF_MAKE_HANDLE(elf_phdr, ptr);
+ }
+
+-const char *elf_section_name(struct elf_binary *elf, const elf_shdr * shdr)
++
++const char *elf_section_name(struct elf_binary *elf,
++ ELF_HANDLE_DECL(elf_shdr) shdr)
+ {
+- if ( elf->sec_strtab == NULL )
++ if ( ELF_PTRVAL_INVALID(elf->sec_strtab) )
+ return "unknown";
++
+ return elf->sec_strtab + elf_uval(elf, shdr, sh_name);
+ }
+
+-const void *elf_section_start(struct elf_binary *elf, const elf_shdr * shdr)
++ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
+ {
+- return elf->image + elf_uval(elf, shdr, sh_offset);
++ return ELF_IMAGE_BASE(elf) + elf_uval(elf, shdr, sh_offset);
+ }
+
+-const void *elf_section_end(struct elf_binary *elf, const elf_shdr * shdr)
++ELF_PTRVAL_CONST_VOID elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
+ {
+- return elf->image
++ return ELF_IMAGE_BASE(elf)
+ + elf_uval(elf, shdr, sh_offset) + elf_uval(elf, shdr, sh_size);
+ }
+
+-const void *elf_segment_start(struct elf_binary *elf, const elf_phdr * phdr)
++ELF_PTRVAL_CONST_VOID elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
+ {
+- return elf->image + elf_uval(elf, phdr, p_offset);
++ return ELF_IMAGE_BASE(elf)
++ + elf_uval(elf, phdr, p_offset);
+ }
+
+-const void *elf_segment_end(struct elf_binary *elf, const elf_phdr * phdr)
++ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
+ {
+- return elf->image
++ return ELF_IMAGE_BASE(elf)
+ + elf_uval(elf, phdr, p_offset) + elf_uval(elf, phdr, p_filesz);
+ }
+
+-const elf_sym *elf_sym_by_name(struct elf_binary *elf, const char *symbol)
++ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol)
+ {
+- const void *ptr = elf_section_start(elf, elf->sym_tab);
+- const void *end = elf_section_end(elf, elf->sym_tab);
+- const elf_sym *sym;
++ ELF_PTRVAL_CONST_VOID ptr = elf_section_start(elf, elf->sym_tab);
++ ELF_PTRVAL_CONST_VOID end = elf_section_end(elf, elf->sym_tab);
++ ELF_HANDLE_DECL(elf_sym) sym;
+ uint64_t info, name;
+
+ for ( ; ptr < end; ptr += elf_size(elf, sym) )
+ {
+- sym = ptr;
++ sym = ELF_MAKE_HANDLE(elf_sym, ptr);
+ info = elf_uval(elf, sym, st_info);
+ name = elf_uval(elf, sym, st_name);
+ if ( ELF32_ST_BIND(info) != STB_GLOBAL )
+@@ -159,33 +163,33 @@ const elf_sym *elf_sym_by_name(struct elf_binary *elf, const char *symbol)
+ continue;
+ return sym;
+ }
+- return NULL;
++ return ELF_INVALID_HANDLE(elf_sym);
+ }
+
+-const elf_sym *elf_sym_by_index(struct elf_binary *elf, int index)
++ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index)
+ {
+- const void *ptr = elf_section_start(elf, elf->sym_tab);
+- const elf_sym *sym;
++ ELF_PTRVAL_CONST_VOID ptr = elf_section_start(elf, elf->sym_tab);
++ ELF_HANDLE_DECL(elf_sym) sym;
+
+- sym = ptr + index * elf_size(elf, sym);
++ sym = ELF_MAKE_HANDLE(elf_sym, ptr + index * elf_size(elf, sym));
+ return sym;
+ }
+
+-const char *elf_note_name(struct elf_binary *elf, const elf_note * note)
++const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
+ {
+- return (void *)note + elf_size(elf, note);
++ return ELF_HANDLE_PTRVAL(note) + elf_size(elf, note);
+ }
+
+-const void *elf_note_desc(struct elf_binary *elf, const elf_note * note)
++ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
+ {
+ int namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
+
+- return (void *)note + elf_size(elf, note) + namesz;
++ return ELF_HANDLE_PTRVAL(note) + elf_size(elf, note) + namesz;
+ }
+
+-uint64_t elf_note_numeric(struct elf_binary *elf, const elf_note * note)
++uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
+ {
+- const void *desc = elf_note_desc(elf, note);
++ ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
+ int descsz = elf_uval(elf, note, descsz);
+
+ switch (descsz)
+@@ -200,10 +204,10 @@ uint64_t elf_note_numeric(struct elf_binary *elf, const elf_note * note)
+ }
+ }
+
+-uint64_t elf_note_numeric_array(struct elf_binary *elf, const elf_note *note,
++uint64_t elf_note_numeric_array(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note,
+ unsigned int unitsz, unsigned int idx)
+ {
+- const void *desc = elf_note_desc(elf, note);
++ ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
+ int descsz = elf_uval(elf, note, descsz);
+
+ if ( descsz % unitsz || idx >= descsz / unitsz )
+@@ -220,12 +224,12 @@ uint64_t elf_note_numeric_array(struct elf_binary *elf, const elf_note *note,
+ }
+ }
+
+-const elf_note *elf_note_next(struct elf_binary *elf, const elf_note * note)
++ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
+ {
+ int namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
+ int descsz = (elf_uval(elf, note, descsz) + 3) & ~3;
+
+- return (void *)note + elf_size(elf, note) + namesz + descsz;
++ return ELF_MAKE_HANDLE(elf_note, ELF_HANDLE_PTRVAL(note) + elf_size(elf, note) + namesz + descsz);
+ }
+
+ /* ------------------------------------------------------------------------ */
+@@ -234,10 +238,10 @@ int elf_is_elfbinary(const void *image)
+ {
+ const Elf32_Ehdr *ehdr = image;
+
+- return IS_ELF(*ehdr);
++ return IS_ELF(*ehdr); /* fixme unchecked */
+ }
+
+-int elf_phdr_is_loadable(struct elf_binary *elf, const elf_phdr * phdr)
++int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
+ {
+ uint64_t p_type = elf_uval(elf, phdr, p_type);
+ uint64_t p_flags = elf_uval(elf, phdr, p_flags);
+diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
+index 38e490c..bdfe323 100644
+--- a/xen/include/xen/libelf.h
++++ b/xen/include/xen/libelf.h
+@@ -48,6 +48,97 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
+
+ /* ------------------------------------------------------------------------ */
+
++/* Macros for accessing the input image and output area. */
++
++/*
++ * We abstract away the pointerness of these pointers, replacing
++ * various void*, char* and struct* with the following:
++ * PTRVAL A pointer to a byte; one can do pointer arithmetic
++ * on this.
++ * This replaces variables which were char*,void*
++ * and their const versions, so we provide four
++ * different declaration macros:
++ * ELF_PTRVAL_{,CONST}{VOID,CHAR}
++ * HANDLE A pointer to a struct. There is one of these types
++ * for each pointer type - that is, for each "structname".
++ * In the arguments to the various HANDLE macros, structname
++ * must be a single identifier which is a typedef.
++ * It is not permitted to do arithmetic on these
++ * pointers. In the current code attempts to do so will
++ * compile, but in the next patch this will become a
++ * compile error.
++ * We provide two declaration macros for const and
++ * non-const pointers.
++ */
++
++#define ELF_REALPTR2PTRVAL(realpointer) (realpointer)
++ /* Converts an actual C pointer into a PTRVAL */
++
++#define ELF_HANDLE_DECL_NONCONST(structname) structname *
++#define ELF_HANDLE_DECL(structname) const structname *
++ /* Provides a type declaration for a HANDLE. */
++ /* May only be used to declare ONE variable at a time */
++
++#define ELF_PTRVAL_VOID void *
++#define ELF_PTRVAL_CHAR char *
++#define ELF_PTRVAL_CONST_VOID const void *
++#define ELF_PTRVAL_CONST_CHAR const char *
++ /* Provides a type declaration for a PTRVAL. */
++ /* May only be used to declare ONE variable at a time */
++
++#define ELF_DEFINE_HANDLE(structname) /* empty */
++ /*
++ * This must be invoked for each HANDLE type to define
++ * the actual C type used for that kind of HANDLE.
++ */
++
++#define ELF_PRPTRVAL "p"
++ /* printf format a la PRId... for a PTRVAL */
++
++#define ELF_MAKE_HANDLE(structname, ptrval) (ptrval)
++ /* Converts a PTRVAL to a HANDLE */
++
++#define ELF_IMAGE_BASE(elf) ((elf)->image)
++ /* Returns the base of the image as a PTRVAL. */
++
++#define ELF_HANDLE_PTRVAL(handleval) ((void*)(handleval))
++ /* Converts a HANDLE to a PTRVAL. */
++
++#define ELF_OBSOLETE_VOIDP_CAST (void*)(uintptr_t)
++ /*
++ * In some places the existing code needs to
++ * - cast away const (the existing code uses const a fair
++ * bit but actually sometimes wants to write to its input)
++ * from a PTRVAL.
++ * - convert an integer representing a pointer to a PTRVAL
++ * This macro provides a suitable cast.
++ */
++
++#define ELF_UNSAFE_PTR(ptrval) ((void*)(ptrval))
++ /*
++ * Turns a PTRVAL into an actual C pointer. Before this is done
++ * the caller must have ensured that the PTRVAL does in fact point
++ * to a permissible location.
++ */
++
++/* PTRVALs can be INVALID (ie, NULL). */
++#define ELF_INVALID_PTRVAL (NULL) /* returns NULL PTRVAL */
++#define ELF_INVALID_HANDLE(structname) /* returns NULL handle */ \
++ ELF_MAKE_HANDLE(structname, ELF_INVALID_PTRVAL)
++#define ELF_PTRVAL_VALID(ptrval) (ptrval) /* } */
++#define ELF_HANDLE_VALID(handleval) (handleval) /* } predicates */
++#define ELF_PTRVAL_INVALID(ptrval) ((ptrval) == NULL) /* } */
++
++/* For internal use by other macros here */
++#define ELF__HANDLE_FIELD_TYPE(handleval, elm) \
++ typeof((handleval)->elm)
++#define ELF__HANDLE_FIELD_OFFSET(handleval, elm) \
++ offsetof(typeof(*(handleval)),elm)
++
++
++/* ------------------------------------------------------------------------ */
++
++
+ typedef union {
+ Elf32_Ehdr e32;
+ Elf64_Ehdr e64;
+@@ -83,6 +174,12 @@ typedef union {
+ Elf64_Note e64;
+ } elf_note;
+
++ELF_DEFINE_HANDLE(elf_ehdr)
++ELF_DEFINE_HANDLE(elf_shdr)
++ELF_DEFINE_HANDLE(elf_phdr)
++ELF_DEFINE_HANDLE(elf_sym)
++ELF_DEFINE_HANDLE(elf_note)
++
+ struct elf_binary {
+ /* elf binary */
+ const char *image;
+@@ -90,10 +187,10 @@ struct elf_binary {
+ char class;
+ char data;
+
+- const elf_ehdr *ehdr;
+- const char *sec_strtab;
+- const elf_shdr *sym_tab;
+- const char *sym_strtab;
++ ELF_HANDLE_DECL(elf_ehdr) ehdr;
++ ELF_PTRVAL_CONST_CHAR sec_strtab;
++ ELF_HANDLE_DECL(elf_shdr) sym_tab;
++ ELF_PTRVAL_CONST_CHAR sym_strtab;
+
+ /* loaded to */
+ char *dest;
+@@ -135,45 +232,72 @@ struct elf_binary {
+ : elf_access_unsigned((elf), (str), \
+ offsetof(typeof(*(str)),e32.elem), \
+ sizeof((str)->e32.elem)))
++ /*
++ * Reads an unsigned field in a header structure in the ELF.
++ * str is a HANDLE, and elem is the field name in it.
++ */
+
+ #define elf_size(elf, str) \
+ ((ELFCLASS64 == (elf)->class) \
+ ? sizeof((str)->e64) : sizeof((str)->e32))
++ /*
++ * Returns the size of the substructure for the appropriate 32/64-bitness.
++ * str should be a HANDLE.
++ */
+
+-uint64_t elf_access_unsigned(struct elf_binary *elf, const void *ptr,
++uint64_t elf_access_unsigned(struct elf_binary *elf, ELF_PTRVAL_CONST_VOID ptr,
+ uint64_t offset, size_t size);
++ /* Reads a field at arbitrary offset and alignemnt */
+
+ uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr);
+
++
++#define elf_memcpy_safe(elf, dst, src, sz) memcpy((dst),(src),(sz))
++#define elf_memset_safe(elf, dst, c, sz) memset((dst),(c),(sz))
++ /*
++ * Versions of memcpy and memset which will (in the next patch)
++ * arrange never to write outside permitted areas.
++ */
++
++#define elf_store_val(elf, type, ptr, val) (*(type*)(ptr) = (val))
++ /* Stores a value at a particular PTRVAL. */
++
++#define elf_store_field(elf, hdr, elm, val) \
++ (elf_store_val((elf), ELF__HANDLE_FIELD_TYPE(hdr, elm), \
++ &((hdr)->elm), \
++ (val)))
++ /* Stores a 32/64-bit field. hdr is a HANDLE and elm is the field name. */
++
++
+ /* ------------------------------------------------------------------------ */
+ /* xc_libelf_tools.c */
+
+ int elf_shdr_count(struct elf_binary *elf);
+ int elf_phdr_count(struct elf_binary *elf);
+
+-const elf_shdr *elf_shdr_by_name(struct elf_binary *elf, const char *name);
+-const elf_shdr *elf_shdr_by_index(struct elf_binary *elf, int index);
+-const elf_phdr *elf_phdr_by_index(struct elf_binary *elf, int index);
++ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *name);
++ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index);
++ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, int index);
+
+-const char *elf_section_name(struct elf_binary *elf, const elf_shdr * shdr);
+-const void *elf_section_start(struct elf_binary *elf, const elf_shdr * shdr);
+-const void *elf_section_end(struct elf_binary *elf, const elf_shdr * shdr);
++const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
++ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
++ELF_PTRVAL_CONST_VOID elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
+
+-const void *elf_segment_start(struct elf_binary *elf, const elf_phdr * phdr);
+-const void *elf_segment_end(struct elf_binary *elf, const elf_phdr * phdr);
++ELF_PTRVAL_CONST_VOID elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
++ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
+
+-const elf_sym *elf_sym_by_name(struct elf_binary *elf, const char *symbol);
+-const elf_sym *elf_sym_by_index(struct elf_binary *elf, int index);
++ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol);
++ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index);
+
+-const char *elf_note_name(struct elf_binary *elf, const elf_note * note);
+-const void *elf_note_desc(struct elf_binary *elf, const elf_note * note);
+-uint64_t elf_note_numeric(struct elf_binary *elf, const elf_note * note);
+-uint64_t elf_note_numeric_array(struct elf_binary *, const elf_note *,
++const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
++ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
++uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
++uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
+ unsigned int unitsz, unsigned int idx);
+-const elf_note *elf_note_next(struct elf_binary *elf, const elf_note * note);
++ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
+
+ int elf_is_elfbinary(const void *image);
+-int elf_phdr_is_loadable(struct elf_binary *elf, const elf_phdr * phdr);
++int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
+
+ /* ------------------------------------------------------------------------ */
+ /* xc_libelf_loader.c */
+@@ -189,7 +313,7 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback*,
+ void elf_parse_binary(struct elf_binary *elf);
+ int elf_load_binary(struct elf_binary *elf);
+
+-void *elf_get_ptr(struct elf_binary *elf, unsigned long addr);
++ELF_PTRVAL_VOID elf_get_ptr(struct elf_binary *elf, unsigned long addr);
+ uint64_t elf_lookup_addr(struct elf_binary *elf, const char *symbol);
+
+ void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart); /* private */
+@@ -221,9 +345,9 @@ struct xen_elfnote {
+
+ struct elf_dom_parms {
+ /* raw */
+- const char *guest_info;
+- const void *elf_note_start;
+- const void *elf_note_end;
++ ELF_PTRVAL_CONST_CHAR guest_info;
++ ELF_PTRVAL_CONST_VOID elf_note_start;
++ ELF_PTRVAL_CONST_VOID elf_note_end;
+ struct xen_elfnote elf_notes[XEN_ELFNOTE_MAX + 1];
+
+ /* parsed */
+@@ -262,10 +386,22 @@ int elf_xen_parse_features(const char *features,
+ uint32_t *required);
+ int elf_xen_parse_note(struct elf_binary *elf,
+ struct elf_dom_parms *parms,
+- const elf_note *note);
++ ELF_HANDLE_DECL(elf_note) note);
+ int elf_xen_parse_guest_info(struct elf_binary *elf,
+ struct elf_dom_parms *parms);
+ int elf_xen_parse(struct elf_binary *elf,
+ struct elf_dom_parms *parms);
+
++#define elf_memcpy_unchecked memcpy
++#define elf_memset_unchecked memset
++ /*
++ * Unsafe versions of memcpy and memset which take actual C
++ * pointers. These are just like real memcpy and memset.
++ */
++
++
++#define ELF_ADVANCE_DEST(elf, amount) elf->dest += (amount)
++ /* Advances past amount bytes of the current destination area. */
++
++
+ #endif /* __XEN_LIBELF_H__ */
+--
+1.7.2.5
+
diff --git a/xsa55-4.20008-tools-xcutils-readnotes-adjust-print_l1_mfn_valid_no.patch b/xsa55-4.20008-tools-xcutils-readnotes-adjust-print_l1_mfn_valid_no.patch
new file mode 100644
index 0000000..e18b410
--- /dev/null
+++ b/xsa55-4.20008-tools-xcutils-readnotes-adjust-print_l1_mfn_valid_no.patch
@@ -0,0 +1,58 @@
+From 7fb404ee7c2ffa61f8d3be1a99cee1dcdcf87970 Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 24 May 2013 17:52:42 +0100
+Subject: [PATCH 08/16] tools/xcutils/readnotes: adjust print_l1_mfn_valid_note
+
+Use the new PTRVAL macros and elf_access_unsigned in
+print_l1_mfn_valid_note.
+
+No functional change unless the input is wrong, or we are reading a
+file for a different endianness.
+
+Separated out from the previous patch because this change does produce
+a difference in the generated code.
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+Acked-by: Ian Campbell <ian.campbell at citrix.com>
+
+v2: Split out into its own patch.
+---
+ tools/xcutils/readnotes.c | 11 ++++++-----
+ 1 files changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
+index 2af047d..7ff2530 100644
+--- a/tools/xcutils/readnotes.c
++++ b/tools/xcutils/readnotes.c
+@@ -77,22 +77,23 @@ static void print_numeric_note(const char *prefix, struct elf_binary *elf,
+ }
+
+ static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf,
+- const elf_note *note)
++ ELF_HANDLE_DECL(elf_note) note)
+ {
+ int descsz = elf_uval(elf, note, descsz);
+- const uint32_t *desc32 = elf_note_desc(elf, note);
+- const uint64_t *desc64 = elf_note_desc(elf, note);
++ ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
+
+ /* XXX should be able to cope with a list of values. */
+ switch ( descsz / 2 )
+ {
+ case 8:
+ printf("%s: mask=%#"PRIx64" value=%#"PRIx64"\n", prefix,
+- desc64[0], desc64[1]);
++ elf_access_unsigned(elf, desc, 0, 8),
++ elf_access_unsigned(elf, desc, 8, 8));
+ break;
+ case 4:
+ printf("%s: mask=%#"PRIx32" value=%#"PRIx32"\n", prefix,
+- desc32[0],desc32[1]);
++ (uint32_t)elf_access_unsigned(elf, desc, 0, 4),
++ (uint32_t)elf_access_unsigned(elf, desc, 4, 4));
+ break;
+ }
+
+--
+1.7.2.5
+
diff --git a/xsa55-4.20009-libelf-check-nul-terminated-strings-properly.patch b/xsa55-4.20009-libelf-check-nul-terminated-strings-properly.patch
new file mode 100644
index 0000000..99487a6
--- /dev/null
+++ b/xsa55-4.20009-libelf-check-nul-terminated-strings-properly.patch
@@ -0,0 +1,203 @@
+From 01ca8af5fdd11099bf2aebc68c528808729de56f Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 24 May 2013 17:52:42 +0100
+Subject: [PATCH 09/16] libelf: check nul-terminated strings properly
+
+It is not safe to simply take pointers into the ELF and use them as C
+pointers. They might not be properly nul-terminated (and the pointers
+might be wild).
+
+So we are going to introduce a new function elf_strval for safely
+getting strings. This will check that the addresses are in range and
+that there is a proper nul-terminated string. Of course it might
+discover that there isn't. In that case, it will be made to fail.
+This means that elf_note_name might fail, too.
+
+For the benefit of call sites which are just going to pass the value
+to a printf-like function, we provide elf_strfmt which returns
+"(invalid)" on failure rather than NULL.
+
+In this patch we introduce dummy definitions of these functions. We
+introduce calls to elf_strval and elf_strfmt everywhere, and update
+all the call sites with appropriate error checking.
+
+There is not yet any semantic change, since before this patch all the
+places where we introduce elf_strval dereferenced the value anyway, so
+it mustn't have been NULL.
+
+In future patches, when elf_strval is made able return NULL, when it
+does so it will mark the elf "broken" so that an appropriate
+diagnostic can be printed.
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+Acked-by: Ian Campbell <ian.campbell at citrix.com>
+Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk at oracle.com>
+
+v2: Fix coding style, in one "if" statement.
+---
+ tools/xcutils/readnotes.c | 10 +++++++---
+ xen/common/libelf/libelf-dominfo.c | 13 ++++++++++---
+ xen/common/libelf/libelf-tools.c | 10 +++++++---
+ xen/include/xen/libelf.h | 7 +++++--
+ 4 files changed, 29 insertions(+), 11 deletions(-)
+
+diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
+index 7ff2530..ca86ba5 100644
+--- a/tools/xcutils/readnotes.c
++++ b/tools/xcutils/readnotes.c
+@@ -63,7 +63,7 @@ struct setup_header {
+ static void print_string_note(const char *prefix, struct elf_binary *elf,
+ ELF_HANDLE_DECL(elf_note) note)
+ {
+- printf("%s: %s\n", prefix, (char*)elf_note_desc(elf, note));
++ printf("%s: %s\n", prefix, elf_strfmt(elf, elf_note_desc(elf, note)));
+ }
+
+ static void print_numeric_note(const char *prefix, struct elf_binary *elf,
+@@ -103,10 +103,13 @@ static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start,
+ {
+ ELF_HANDLE_DECL(elf_note) note;
+ int notes_found = 0;
++ const char *this_note_name;
+
+ for ( note = start; ELF_HANDLE_PTRVAL(note) < ELF_HANDLE_PTRVAL(end); note = elf_note_next(elf, note) )
+ {
+- if (0 != strcmp(elf_note_name(elf, note), "Xen"))
++ this_note_name = elf_note_name(elf, note);
++ if (NULL == this_note_name ||
++ 0 != strcmp(this_note_name, "Xen"))
+ continue;
+
+ notes_found++;
+@@ -294,7 +297,8 @@ int main(int argc, char **argv)
+
+ shdr = elf_shdr_by_name(&elf, "__xen_guest");
+ if (ELF_HANDLE_VALID(shdr))
+- printf("__xen_guest: %s\n", (char*)elf_section_start(&elf, shdr));
++ printf("__xen_guest: %s\n",
++ elf_strfmt(&elf, elf_section_start(&elf, shdr)));
+
+ return 0;
+ }
+diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
+index 7140d59..b217f8f 100644
+--- a/xen/common/libelf/libelf-dominfo.c
++++ b/xen/common/libelf/libelf-dominfo.c
+@@ -137,7 +137,10 @@ int elf_xen_parse_note(struct elf_binary *elf,
+
+ if ( note_desc[type].str )
+ {
+- str = elf_note_desc(elf, note);
++ str = elf_strval(elf, elf_note_desc(elf, note));
++ if (str == NULL)
++ /* elf_strval will mark elf broken if it fails so no need to log */
++ return 0;
+ elf_msg(elf, "%s: %s = \"%s\"\n", __FUNCTION__,
+ note_desc[type].name, str);
+ parms->elf_notes[type].type = XEN_ENT_STR;
+@@ -220,6 +223,7 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
+ {
+ int xen_elfnotes = 0;
+ ELF_HANDLE_DECL(elf_note) note;
++ const char *note_name;
+
+ parms->elf_note_start = start;
+ parms->elf_note_end = end;
+@@ -227,7 +231,10 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
+ ELF_HANDLE_PTRVAL(note) < parms->elf_note_end;
+ note = elf_note_next(elf, note) )
+ {
+- if ( strcmp(elf_note_name(elf, note), "Xen") )
++ note_name = elf_note_name(elf, note);
++ if ( note_name == NULL )
++ continue;
++ if ( strcmp(note_name, "Xen") )
+ continue;
+ if ( elf_xen_parse_note(elf, parms, note) )
+ return -1;
+@@ -541,7 +548,7 @@ int elf_xen_parse(struct elf_binary *elf,
+ parms->elf_note_start = ELF_INVALID_PTRVAL;
+ parms->elf_note_end = ELF_INVALID_PTRVAL;
+ elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__,
+- parms->guest_info);
++ elf_strfmt(elf, parms->guest_info));
+ elf_xen_parse_guest_info(elf, parms);
+ break;
+ }
+diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
+index f1fd886..3a0cde1 100644
+--- a/xen/common/libelf/libelf-tools.c
++++ b/xen/common/libelf/libelf-tools.c
+@@ -119,7 +119,7 @@ const char *elf_section_name(struct elf_binary *elf,
+ if ( ELF_PTRVAL_INVALID(elf->sec_strtab) )
+ return "unknown";
+
+- return elf->sec_strtab + elf_uval(elf, shdr, sh_name);
++ return elf_strval(elf, elf->sec_strtab + elf_uval(elf, shdr, sh_name));
+ }
+
+ ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
+@@ -151,6 +151,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym
+ ELF_PTRVAL_CONST_VOID end = elf_section_end(elf, elf->sym_tab);
+ ELF_HANDLE_DECL(elf_sym) sym;
+ uint64_t info, name;
++ const char *sym_name;
+
+ for ( ; ptr < end; ptr += elf_size(elf, sym) )
+ {
+@@ -159,7 +160,10 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym
+ name = elf_uval(elf, sym, st_name);
+ if ( ELF32_ST_BIND(info) != STB_GLOBAL )
+ continue;
+- if ( strcmp(elf->sym_strtab + name, symbol) )
++ sym_name = elf_strval(elf, elf->sym_strtab + name);
++ if ( sym_name == NULL ) /* out of range, oops */
++ return ELF_INVALID_HANDLE(elf_sym);
++ if ( strcmp(sym_name, symbol) )
+ continue;
+ return sym;
+ }
+@@ -177,7 +181,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index)
+
+ const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
+ {
+- return ELF_HANDLE_PTRVAL(note) + elf_size(elf, note);
++ return elf_strval(elf, ELF_HANDLE_PTRVAL(note) + elf_size(elf, note));
+ }
+
+ ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
+diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
+index bdfe323..8049cdc 100644
+--- a/xen/include/xen/libelf.h
++++ b/xen/include/xen/libelf.h
+@@ -252,6 +252,9 @@ uint64_t elf_access_unsigned(struct elf_binary *elf, ELF_PTRVAL_CONST_VOID ptr,
+ uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr);
+
+
++#define elf_strval(elf,x) ((const char*)(x)) /* may return NULL in the future */
++#define elf_strfmt(elf,x) ((const char*)(x)) /* will return (invalid) instead */
++
+ #define elf_memcpy_safe(elf, dst, src, sz) memcpy((dst),(src),(sz))
+ #define elf_memset_safe(elf, dst, c, sz) memset((dst),(c),(sz))
+ /*
+@@ -279,7 +282,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
+ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index);
+ ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, int index);
+
+-const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
++const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr); /* might return NULL if inputs are invalid */
+ ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
+ ELF_PTRVAL_CONST_VOID elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
+
+@@ -289,7 +292,7 @@ ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(el
+ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol);
+ ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index);
+
+-const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
++const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); /* may return NULL */
+ ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
+ uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
+ uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
+--
+1.7.2.5
+
diff --git a/xsa55-4.20010-libelf-check-all-pointer-accesses.patch b/xsa55-4.20010-libelf-check-all-pointer-accesses.patch
new file mode 100644
index 0000000..3107064
--- /dev/null
+++ b/xsa55-4.20010-libelf-check-all-pointer-accesses.patch
@@ -0,0 +1,820 @@
+From bc14f1dd3f22d609a52edbe9b053180446e0068b Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 24 May 2013 17:52:42 +0100
+Subject: [PATCH 10/16] libelf: check all pointer accesses
+
+We change the ELF_PTRVAL and ELF_HANDLE types and associated macros:
+
+ * PTRVAL becomes a uintptr_t, for which we provide a typedef
+ elf_ptrval. This means no arithmetic done on it can overflow so
+ the compiler cannot do any malicious invalid pointer arithmetic
+ "optimisations". It also means that any places where we
+ dereference one of these pointers without using the appropriate
+ macros or functions become a compilation error.
+
+ So we can be sure that we won't miss any memory accesses.
+
+ All the PTRVAL variables were previously void* or char*, so
+ the actual address calculations are unchanged.
+
+ * ELF_HANDLE becomes a union, one half of which keeps the pointer
+ value and the other half of which is just there to record the
+ type.
+
+ The new type is not a pointer type so there can be no address
+ calculations on it whose meaning would change. Every assignment or
+ access has to go through one of our macros.
+
+ * The distinction between const and non-const pointers and char*s
+ and void*s in libelf goes away. This was not important (and
+ anyway libelf tended to cast away const in various places).
+
+ * The fields elf->image and elf->dest are renamed. That proves
+ that we haven't missed any unchecked uses of these actual
+ pointer values.
+
+ * The caller may fill in elf->caller_xdest_base and _size to
+ specify another range of memory which is safe for libelf to
+ access, besides the input and output images.
+
+ * When accesses fail due to being out of range, we mark the elf
+ "broken". This will be checked and used for diagnostics in
+ a following patch.
+
+ We do not check for write accesses to the input image. This is
+ because libelf actually does this in a number of places. So we
+ simply permit that.
+
+ * Each caller of libelf which used to set dest now sets
+ dest_base and dest_size.
+
+ * In xc_dom_load_elf_symtab we provide a new actual-pointer
+ value hdr_ptr which we get from mapping the guest's kernel
+ area and use (checking carefully) as the caller_xdest area.
+
+ * The STAR(h) macro in libelf-dominfo.c now uses elf_access_unsigned.
+
+ * elf-init uses the new elf_uval_3264 accessor to access the 32-bit
+ fields, rather than an unchecked field access (ie, unchecked
+ pointer access).
+
+ * elf_uval has been reworked to use elf_uval_3264. Both of these
+ macros are essentially new in this patch (although they are derived
+ from the old elf_uval) and need careful review.
+
+ * ELF_ADVANCE_DEST is now safe in the sense that you can use it to
+ chop parts off the front of the dest area but if you chop more than
+ is available, the dest area is simply set to be empty, preventing
+ future accesses.
+
+ * We introduce some #defines for memcpy, memset, memmove and strcpy:
+ - We provide elf_memcpy_safe and elf_memset_safe which take
+ PTRVALs and do checking on the supplied pointers.
+ - Users inside libelf must all be changed to either
+ elf_mem*_unchecked (which are just like mem*), or
+ elf_mem*_safe (which take PTRVALs) and are checked. Any
+ unchanged call sites become compilation errors.
+
+ * We do _not_ at this time fix elf_access_unsigned so that it doesn't
+ make unaligned accesses. We hope that unaligned accesses are OK on
+ every supported architecture. But it does check the supplied
+ pointer for validity.
+
+Additional changes in 4.2 backport:
+
+* ELF_PRPTRVAL needs to be defined oddly on 4.2 and earlier because
+ while Xen's headers provide a definition of PRIuPTR, it doesn't
+ match the type of uintptr_t so it causes compilation errors.
+
+* To support 32-bit builds, ELF_UNSAFE_PTR contains an explicit cast
+ to uintptr_t in case the argument isn't the same size. On 32-bit
+ some of the values converted to pointers are 64-bit.
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+
+v3.1:
+ Introduce a change to elf_store_field to undo the effects of
+ the v3.1 change to the previous patch (the definition there
+ is not compatible with the new types).
+
+v3: Fix a whitespace error.
+
+v2 Acked-by: Ian Campbell <ian.campbell at citrix.com>
+
+v2: BUGFIX: elf_strval: Fix loop termination condition to actually work.
+ BUGFIX: elf_strval: Fix return value to not always be totally wild.
+ BUGFIX: xc_dom_load_elf_symtab: do proper check for small header size.
+ xc_dom_load_elf_symtab: narrow scope of `hdr_ptr'.
+ xc_dom_load_elf_symtab: split out uninit'd symtab.class ref fix.
+ More comments on the lifetime/validity of elf-> dest ptrs etc.
+ libelf.h: write "obsolete" out in full
+ libelf.h: rename "dontuse" to "typeonly" and add doc comment
+ elf_ptrval_in_range: Document trustedness of arguments.
+ Style and commit message fixes.
+---
+ tools/libxc/xc_dom_elfloader.c | 49 ++++++++-
+ tools/libxc/xc_hvm_build_x86.c | 10 +-
+ xen/arch/x86/domain_build.c | 3 +-
+ xen/common/libelf/libelf-dominfo.c | 2 +-
+ xen/common/libelf/libelf-loader.c | 16 ++--
+ xen/common/libelf/libelf-private.h | 13 +++
+ xen/common/libelf/libelf-tools.c | 103 ++++++++++++++++++-
+ xen/include/xen/libelf.h | 194 +++++++++++++++++++++++++-----------
+ 8 files changed, 305 insertions(+), 85 deletions(-)
+
+diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
+index e481649..80152bf 100644
+--- a/tools/libxc/xc_dom_elfloader.c
++++ b/tools/libxc/xc_dom_elfloader.c
+@@ -120,6 +120,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+ ELF_PTRVAL_CHAR hdr;
+ size_t size;
+ int h, count, type, i, tables = 0;
++ unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
+
+ if ( elf_swap(elf) )
+ {
+@@ -130,19 +131,30 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+
+ if ( load )
+ {
++ char *hdr_ptr;
++
+ if ( !dom->bsd_symtab_start )
+ return 0;
+ size = dom->kernel_seg.vend - dom->bsd_symtab_start;
+- hdr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start);
+- *(int *)hdr = size - sizeof(int);
++ hdr_ptr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start);
++ elf->caller_xdest_base = hdr_ptr;
++ elf->caller_xdest_size = page_size -
++ (dom->bsd_symtab_start & (page_size-1));
++ hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
++ elf_store_val(elf, int, hdr, size - sizeof(int));
+ }
+ else
+ {
++ char *hdr_ptr;
++
+ size = sizeof(int) + elf_size(elf, elf->ehdr) +
+ elf_shdr_count(elf) * elf_size(elf, shdr);
+- hdr = xc_dom_malloc(dom, size);
+- if ( hdr == NULL )
++ hdr_ptr = xc_dom_malloc(dom, size);
++ if ( hdr_ptr == NULL )
+ return 0;
++ elf->caller_xdest_base = hdr_ptr;
++ elf->caller_xdest_size = size;
++ hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
+ dom->bsd_symtab_start = elf_round_up(elf, dom->kernel_seg.vend);
+ }
+
+@@ -170,9 +182,32 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+ ehdr->e_shoff = elf_size(elf, elf->ehdr);
+ ehdr->e_shstrndx = SHN_UNDEF;
+ }
+- if ( elf_init(&syms, hdr + sizeof(int), size - sizeof(int)) )
++ if ( elf->caller_xdest_size < sizeof(int) )
++ {
++ DOMPRINTF("%s/%s: header size %"PRIx64" too small",
++ __FUNCTION__, load ? "load" : "parse",
++ (uint64_t)elf->caller_xdest_size);
++ return -1;
++ }
++ if ( elf_init(&syms, elf->caller_xdest_base + sizeof(int),
++ elf->caller_xdest_size - sizeof(int)) )
+ return -1;
+
++ /*
++ * The caller_xdest_{base,size} and dest_{base,size} need to
++ * remain valid so long as each struct elf_image does. The
++ * principle we adopt is that these values are set when the
++ * memory is allocated or mapped, and cleared when (and if)
++ * they are unmapped.
++ *
++ * Mappings of the guest are normally undone by xc_dom_unmap_all
++ * (directly or via xc_dom_release). We do not explicitly clear
++ * these because in fact that happens only at the end of
++ * xc_dom_boot_image, at which time all of these ELF loading
++ * functions have returned. No relevant struct elf_binary*
++ * escapes this file.
++ */
++
+ xc_elf_set_logfile(dom->xch, &syms, 1);
+
+ symtab = dom->bsd_symtab_start + sizeof(int);
+@@ -311,8 +346,10 @@ static int xc_dom_load_elf_kernel(struct xc_dom_image *dom)
+ {
+ struct elf_binary *elf = dom->private_loader;
+ int rc;
++ xen_pfn_t pages;
+
+- elf->dest = xc_dom_seg_to_ptr(dom, &dom->kernel_seg);
++ elf->dest_base = xc_dom_seg_to_ptr_pages(dom, &dom->kernel_seg, &pages);
++ elf->dest_size = pages * XC_DOM_PAGE_SIZE(dom);
+ rc = elf_load_binary(elf);
+ if ( rc < 0 )
+ {
+diff --git a/tools/libxc/xc_hvm_build_x86.c b/tools/libxc/xc_hvm_build_x86.c
+index 15b603d..ccfd8b5 100644
+--- a/tools/libxc/xc_hvm_build_x86.c
++++ b/tools/libxc/xc_hvm_build_x86.c
+@@ -104,11 +104,12 @@ static int loadelfimage(
+ for ( i = 0; i < pages; i++ )
+ entries[i].mfn = parray[(elf->pstart >> PAGE_SHIFT) + i];
+
+- elf->dest = xc_map_foreign_ranges(
++ elf->dest_base = xc_map_foreign_ranges(
+ xch, dom, pages << PAGE_SHIFT, PROT_READ | PROT_WRITE, 1 << PAGE_SHIFT,
+ entries, pages);
+- if ( elf->dest == NULL )
++ if ( elf->dest_base == NULL )
+ goto err;
++ elf->dest_size = pages * PAGE_SIZE;
+
+ ELF_ADVANCE_DEST(elf, elf->pstart & (PAGE_SIZE - 1));
+
+@@ -117,8 +118,9 @@ static int loadelfimage(
+ if ( rc < 0 )
+ PERROR("Failed to load elf binary\n");
+
+- munmap(elf->dest, pages << PAGE_SHIFT);
+- elf->dest = NULL;
++ munmap(elf->dest_base, pages << PAGE_SHIFT);
++ elf->dest_base = NULL;
++ elf->dest_size = 0;
+
+ err:
+ free(entries);
+diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c
+index 469d363..a655b21 100644
+--- a/xen/arch/x86/domain_build.c
++++ b/xen/arch/x86/domain_build.c
+@@ -908,7 +908,8 @@ int __init construct_dom0(
+ write_ptbase(v);
+
+ /* Copy the OS image and free temporary buffer. */
+- elf.dest = (void*)vkern_start;
++ elf.dest_base = (void*)vkern_start;
++ elf.dest_size = vkern_end - vkern_start;
+ rc = elf_load_binary(&elf);
+ if ( rc < 0 )
+ {
+diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
+index b217f8f..98c80dc 100644
+--- a/xen/common/libelf/libelf-dominfo.c
++++ b/xen/common/libelf/libelf-dominfo.c
+@@ -254,7 +254,7 @@ int elf_xen_parse_guest_info(struct elf_binary *elf,
+ int len;
+
+ h = parms->guest_info;
+-#define STAR(h) (*(h))
++#define STAR(h) (elf_access_unsigned(elf, (h), 0, 1))
+ while ( STAR(h) )
+ {
+ elf_memset_unchecked(name, 0, sizeof(name));
+diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
+index 0fef84c..a3310e7 100644
+--- a/xen/common/libelf/libelf-loader.c
++++ b/xen/common/libelf/libelf-loader.c
+@@ -24,23 +24,25 @@
+
+ /* ------------------------------------------------------------------------ */
+
+-int elf_init(struct elf_binary *elf, const char *image, size_t size)
++int elf_init(struct elf_binary *elf, const char *image_input, size_t size)
+ {
+ ELF_HANDLE_DECL(elf_shdr) shdr;
+ uint64_t i, count, section, offset;
+
+- if ( !elf_is_elfbinary(image) )
++ if ( !elf_is_elfbinary(image_input) )
+ {
+ elf_err(elf, "%s: not an ELF binary\n", __FUNCTION__);
+ return -1;
+ }
+
+ elf_memset_unchecked(elf, 0, sizeof(*elf));
+- elf->image = image;
++ elf->image_base = image_input;
+ elf->size = size;
+- elf->ehdr = (elf_ehdr *)image;
+- elf->class = elf->ehdr->e32.e_ident[EI_CLASS];
+- elf->data = elf->ehdr->e32.e_ident[EI_DATA];
++ elf->ehdr = ELF_MAKE_HANDLE(elf_ehdr, (elf_ptrval)image_input);
++ elf->class = elf_uval_3264(elf, elf->ehdr, e32.e_ident[EI_CLASS]);
++ elf->data = elf_uval_3264(elf, elf->ehdr, e32.e_ident[EI_DATA]);
++ elf->caller_xdest_base = NULL;
++ elf->caller_xdest_size = 0;
+
+ /* Sanity check phdr. */
+ offset = elf_uval(elf, elf->ehdr, e_phoff) +
+@@ -300,7 +302,7 @@ int elf_load_binary(struct elf_binary *elf)
+
+ ELF_PTRVAL_VOID elf_get_ptr(struct elf_binary *elf, unsigned long addr)
+ {
+- return elf->dest + addr - elf->pstart;
++ return ELF_REALPTR2PTRVAL(elf->dest_base) + addr - elf->pstart;
+ }
+
+ uint64_t elf_lookup_addr(struct elf_binary * elf, const char *symbol)
+diff --git a/xen/common/libelf/libelf-private.h b/xen/common/libelf/libelf-private.h
+index 3ef753c..280dfd1 100644
+--- a/xen/common/libelf/libelf-private.h
++++ b/xen/common/libelf/libelf-private.h
+@@ -86,6 +86,19 @@ do { strncpy((d),(s),sizeof((d))-1); \
+
+ #endif
+
++#undef memcpy
++#undef memset
++#undef memmove
++#undef strcpy
++
++#define memcpy MISTAKE_unspecified_memcpy
++#define memset MISTAKE_unspecified_memset
++#define memmove MISTAKE_unspecified_memmove
++#define strcpy MISTAKE_unspecified_strcpy
++ /* This prevents libelf from using these undecorated versions
++ * of memcpy, memset, memmove and strcpy. Every call site
++ * must either use elf_mem*_unchecked, or elf_mem*_safe. */
++
+ #endif /* __LIBELF_PRIVATE_H_ */
+
+ /*
+diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
+index 3a0cde1..ed107bc 100644
+--- a/xen/common/libelf/libelf-tools.c
++++ b/xen/common/libelf/libelf-tools.c
+@@ -20,28 +20,97 @@
+
+ /* ------------------------------------------------------------------------ */
+
+-uint64_t elf_access_unsigned(struct elf_binary * elf, const void *ptr,
+- uint64_t offset, size_t size)
++void elf_mark_broken(struct elf_binary *elf, const char *msg)
+ {
++ if ( elf->broken == NULL )
++ elf->broken = msg;
++}
++
++const char *elf_check_broken(const struct elf_binary *elf)
++{
++ return elf->broken;
++}
++
++static int elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
++ const void *region, uint64_t regionsize)
++ /*
++ * Returns true if the putative memory area [ptrval,ptrval+size>
++ * is completely inside the region [region,region+regionsize>.
++ *
++ * ptrval and size are the untrusted inputs to be checked.
++ * region and regionsize are trusted and must be correct and valid.
++ */
++{
++ elf_ptrval regionp = (elf_ptrval)region;
++
++ if ( (ptrval < regionp) || /* start is before region */
++ (ptrval > regionp + regionsize) || /* start is after region */
++ (size > regionsize - (ptrval - regionp)) ) /* too big */
++ return 0;
++ return 1;
++}
++
++int elf_access_ok(struct elf_binary * elf,
++ uint64_t ptrval, size_t size)
++{
++ if ( elf_ptrval_in_range(ptrval, size, elf->image_base, elf->size) )
++ return 1;
++ if ( elf_ptrval_in_range(ptrval, size, elf->dest_base, elf->dest_size) )
++ return 1;
++ if ( elf_ptrval_in_range(ptrval, size,
++ elf->caller_xdest_base, elf->caller_xdest_size) )
++ return 1;
++ elf_mark_broken(elf, "out of range access");
++ return 0;
++}
++
++void elf_memcpy_safe(struct elf_binary *elf, elf_ptrval dst,
++ elf_ptrval src, size_t size)
++{
++ if ( elf_access_ok(elf, dst, size) &&
++ elf_access_ok(elf, src, size) )
++ {
++ /* use memmove because these checks do not prove that the
++ * regions don't overlap and overlapping regions grant
++ * permission for compiler malice */
++ elf_memmove_unchecked(ELF_UNSAFE_PTR(dst), ELF_UNSAFE_PTR(src), size);
++ }
++}
++
++void elf_memset_safe(struct elf_binary *elf, elf_ptrval dst, int c, size_t size)
++{
++ if ( elf_access_ok(elf, dst, size) )
++ {
++ elf_memset_unchecked(ELF_UNSAFE_PTR(dst), c, size);
++ }
++}
++
++uint64_t elf_access_unsigned(struct elf_binary * elf, elf_ptrval base,
++ uint64_t moreoffset, size_t size)
++{
++ elf_ptrval ptrval = base + moreoffset;
+ int need_swap = elf_swap(elf);
+ const uint8_t *u8;
+ const uint16_t *u16;
+ const uint32_t *u32;
+ const uint64_t *u64;
+
++ if ( !elf_access_ok(elf, ptrval, size) )
++ return 0;
++
+ switch ( size )
+ {
+ case 1:
+- u8 = ptr + offset;
++ u8 = (const void*)ptrval;
+ return *u8;
+ case 2:
+- u16 = ptr + offset;
++ u16 = (const void*)ptrval;
+ return need_swap ? bswap_16(*u16) : *u16;
+ case 4:
+- u32 = ptr + offset;
++ u32 = (const void*)ptrval;
+ return need_swap ? bswap_32(*u32) : *u32;
+ case 8:
+- u64 = ptr + offset;
++ u64 = (const void*)ptrval;
+ return need_swap ? bswap_64(*u64) : *u64;
+ default:
+ return 0;
+@@ -122,6 +191,28 @@ const char *elf_section_name(struct elf_binary *elf,
+ return elf_strval(elf, elf->sec_strtab + elf_uval(elf, shdr, sh_name));
+ }
+
++const char *elf_strval(struct elf_binary *elf, elf_ptrval start)
++{
++ uint64_t length;
++
++ for ( length = 0; ; length++ ) {
++ if ( !elf_access_ok(elf, start + length, 1) )
++ return NULL;
++ if ( !elf_access_unsigned(elf, start, length, 1) )
++ /* ok */
++ return ELF_UNSAFE_PTR(start);
++ }
++}
++
++const char *elf_strfmt(struct elf_binary *elf, elf_ptrval start)
++{
++ const char *str = elf_strval(elf, start);
++
++ if ( str == NULL )
++ return "(invalid)";
++ return str;
++}
++
+ ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
+ {
+ return ELF_IMAGE_BASE(elf) + elf_uval(elf, shdr, sh_offset);
+diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
+index 8049cdc..bbde92e 100644
+--- a/xen/include/xen/libelf.h
++++ b/xen/include/xen/libelf.h
+@@ -57,8 +57,9 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
+ * on this.
+ * This replaces variables which were char*,void*
+ * and their const versions, so we provide four
+- * different declaration macros:
++ * different obsolete declaration macros:
+ * ELF_PTRVAL_{,CONST}{VOID,CHAR}
++ * New code can simply use the elf_ptrval typedef.
+ * HANDLE A pointer to a struct. There is one of these types
+ * for each pointer type - that is, for each "structname".
+ * In the arguments to the various HANDLE macros, structname
+@@ -67,54 +68,66 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
+ * pointers. In the current code attempts to do so will
+ * compile, but in the next patch this will become a
+ * compile error.
+- * We provide two declaration macros for const and
+- * non-const pointers.
++ * We also provide a second declaration macro for
++ * pointers which were to const; this is obsolete.
+ */
+
+-#define ELF_REALPTR2PTRVAL(realpointer) (realpointer)
++typedef uintptr_t elf_ptrval;
++
++#define ELF_REALPTR2PTRVAL(realpointer) ((elf_ptrval)(realpointer))
+ /* Converts an actual C pointer into a PTRVAL */
+
+-#define ELF_HANDLE_DECL_NONCONST(structname) structname *
+-#define ELF_HANDLE_DECL(structname) const structname *
++#define ELF_HANDLE_DECL_NONCONST(structname) structname##_handle /*obsolete*/
++#define ELF_HANDLE_DECL(structname) structname##_handle
+ /* Provides a type declaration for a HANDLE. */
+- /* May only be used to declare ONE variable at a time */
+
+-#define ELF_PTRVAL_VOID void *
+-#define ELF_PTRVAL_CHAR char *
+-#define ELF_PTRVAL_CONST_VOID const void *
+-#define ELF_PTRVAL_CONST_CHAR const char *
+- /* Provides a type declaration for a PTRVAL. */
+- /* May only be used to declare ONE variable at a time */
++#define ELF_PTRVAL_VOID elf_ptrval /*obsolete*/
++#define ELF_PTRVAL_CHAR elf_ptrval /*obsolete*/
++#define ELF_PTRVAL_CONST_VOID elf_ptrval /*obsolete*/
++#define ELF_PTRVAL_CONST_CHAR elf_ptrval /*obsolete*/
+
+-#define ELF_DEFINE_HANDLE(structname) /* empty */
++/* printf format a la PRId... for a PTRVAL */
++#ifdef __XEN__
++#define ELF_PRPTRVAL "lu"
++ /*
++ * PRIuPTR is misdefined in xen/include/xen/inttypes.h,
++ * on x86_32, to "u", when in fact uintptr_t is an unsigned long.
++ */
++#else
++#define ELF_PRPTRVAL PRIuPTR
++#endif
++
++#define ELF_DEFINE_HANDLE(structname) \
++ typedef union { \
++ elf_ptrval ptrval; \
++ const structname *typeonly; /* for sizeof, offsetof, &c only */ \
++ } structname##_handle;
+ /*
+ * This must be invoked for each HANDLE type to define
+ * the actual C type used for that kind of HANDLE.
+ */
+
+-#define ELF_PRPTRVAL "p"
+- /* printf format a la PRId... for a PTRVAL */
+-
+-#define ELF_MAKE_HANDLE(structname, ptrval) (ptrval)
++#define ELF_MAKE_HANDLE(structname, ptrval) ((structname##_handle){ ptrval })
+ /* Converts a PTRVAL to a HANDLE */
+
+-#define ELF_IMAGE_BASE(elf) ((elf)->image)
++#define ELF_IMAGE_BASE(elf) ((elf_ptrval)(elf)->image_base)
+ /* Returns the base of the image as a PTRVAL. */
+
+-#define ELF_HANDLE_PTRVAL(handleval) ((void*)(handleval))
++#define ELF_HANDLE_PTRVAL(handleval) ((handleval).ptrval)
+ /* Converts a HANDLE to a PTRVAL. */
+
+-#define ELF_OBSOLETE_VOIDP_CAST (void*)(uintptr_t)
++#define ELF_OBSOLETE_VOIDP_CAST /*empty*/
+ /*
+- * In some places the existing code needs to
++ * In some places the old code used to need to
+ * - cast away const (the existing code uses const a fair
+ * bit but actually sometimes wants to write to its input)
+ * from a PTRVAL.
+ * - convert an integer representing a pointer to a PTRVAL
+- * This macro provides a suitable cast.
++ * Nowadays all of these re uintptr_ts so there is no const problem
++ * and no need for any casting.
+ */
+
+-#define ELF_UNSAFE_PTR(ptrval) ((void*)(ptrval))
++#define ELF_UNSAFE_PTR(ptrval) ((void*)(uintptr_t)(ptrval))
+ /*
+ * Turns a PTRVAL into an actual C pointer. Before this is done
+ * the caller must have ensured that the PTRVAL does in fact point
+@@ -122,23 +135,25 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
+ */
+
+ /* PTRVALs can be INVALID (ie, NULL). */
+-#define ELF_INVALID_PTRVAL (NULL) /* returns NULL PTRVAL */
++#define ELF_INVALID_PTRVAL ((elf_ptrval)0) /* returns NULL PTRVAL */
+ #define ELF_INVALID_HANDLE(structname) /* returns NULL handle */ \
+ ELF_MAKE_HANDLE(structname, ELF_INVALID_PTRVAL)
+-#define ELF_PTRVAL_VALID(ptrval) (ptrval) /* } */
+-#define ELF_HANDLE_VALID(handleval) (handleval) /* } predicates */
+-#define ELF_PTRVAL_INVALID(ptrval) ((ptrval) == NULL) /* } */
++#define ELF_PTRVAL_VALID(ptrval) (!!(ptrval)) /* } */
++#define ELF_HANDLE_VALID(handleval) (!!(handleval).ptrval) /* } predicates */
++#define ELF_PTRVAL_INVALID(ptrval) (!ELF_PTRVAL_VALID((ptrval))) /* } */
++
++#define ELF_MAX_PTRVAL (~(elf_ptrval)0)
++ /* PTRVAL value guaranteed to compare > to any valid PTRVAL */
+
+ /* For internal use by other macros here */
+ #define ELF__HANDLE_FIELD_TYPE(handleval, elm) \
+- typeof((handleval)->elm)
++ typeof((handleval).typeonly->elm)
+ #define ELF__HANDLE_FIELD_OFFSET(handleval, elm) \
+- offsetof(typeof(*(handleval)),elm)
++ offsetof(typeof(*(handleval).typeonly),elm)
+
+
+ /* ------------------------------------------------------------------------ */
+
+-
+ typedef union {
+ Elf32_Ehdr e32;
+ Elf64_Ehdr e64;
+@@ -182,7 +197,7 @@ ELF_DEFINE_HANDLE(elf_note)
+
+ struct elf_binary {
+ /* elf binary */
+- const char *image;
++ const void *image_base;
+ size_t size;
+ char class;
+ char data;
+@@ -190,10 +205,16 @@ struct elf_binary {
+ ELF_HANDLE_DECL(elf_ehdr) ehdr;
+ ELF_PTRVAL_CONST_CHAR sec_strtab;
+ ELF_HANDLE_DECL(elf_shdr) sym_tab;
+- ELF_PTRVAL_CONST_CHAR sym_strtab;
++ uint64_t sym_strtab;
+
+ /* loaded to */
+- char *dest;
++ /*
++ * dest_base and dest_size are trusted and must be correct;
++ * whenever dest_size is not 0, both of these must be valid
++ * so long as the struct elf_binary is in use.
++ */
++ char *dest_base;
++ size_t dest_size;
+ uint64_t pstart;
+ uint64_t pend;
+ uint64_t reloc_offset;
+@@ -201,12 +222,22 @@ struct elf_binary {
+ uint64_t bsd_symtab_pstart;
+ uint64_t bsd_symtab_pend;
+
++ /*
++ * caller's other acceptable destination
++ *
++ * Again, these are trusted and must be valid (or 0) so long
++ * as the struct elf_binary is in use.
++ */
++ void *caller_xdest_base;
++ uint64_t caller_xdest_size;
++
+ #ifndef __XEN__
+ /* misc */
+ elf_log_callback *log_callback;
+ void *log_caller_data;
+ #endif
+ int verbose;
++ const char *broken;
+ };
+
+ /* ------------------------------------------------------------------------ */
+@@ -224,22 +255,27 @@ struct elf_binary {
+ #define elf_lsb(elf) (ELFDATA2LSB == (elf)->data)
+ #define elf_swap(elf) (NATIVE_ELFDATA != (elf)->data)
+
+-#define elf_uval(elf, str, elem) \
+- ((ELFCLASS64 == (elf)->class) \
+- ? elf_access_unsigned((elf), (str), \
+- offsetof(typeof(*(str)),e64.elem), \
+- sizeof((str)->e64.elem)) \
+- : elf_access_unsigned((elf), (str), \
+- offsetof(typeof(*(str)),e32.elem), \
+- sizeof((str)->e32.elem)))
++#define elf_uval_3264(elf, handle, elem) \
++ elf_access_unsigned((elf), (handle).ptrval, \
++ offsetof(typeof(*(handle).typeonly),elem), \
++ sizeof((handle).typeonly->elem))
++
++#define elf_uval(elf, handle, elem) \
++ ((ELFCLASS64 == (elf)->class) \
++ ? elf_uval_3264(elf, handle, e64.elem) \
++ : elf_uval_3264(elf, handle, e32.elem))
+ /*
+ * Reads an unsigned field in a header structure in the ELF.
+ * str is a HANDLE, and elem is the field name in it.
+ */
+
+-#define elf_size(elf, str) \
++
++#define elf_size(elf, handle_or_handletype) ({ \
++ typeof(handle_or_handletype) elf_size__dummy; \
+ ((ELFCLASS64 == (elf)->class) \
+- ? sizeof((str)->e64) : sizeof((str)->e32))
++ ? sizeof(elf_size__dummy.typeonly->e64) \
++ : sizeof(elf_size__dummy.typeonly->e32)); \
++})
+ /*
+ * Returns the size of the substructure for the appropriate 32/64-bitness.
+ * str should be a HANDLE.
+@@ -251,23 +287,37 @@ uint64_t elf_access_unsigned(struct elf_binary *elf, ELF_PTRVAL_CONST_VOID ptr,
+
+ uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr);
+
++const char *elf_strval(struct elf_binary *elf, elf_ptrval start);
++ /* may return NULL if the string is out of range etc. */
+
+-#define elf_strval(elf,x) ((const char*)(x)) /* may return NULL in the future */
+-#define elf_strfmt(elf,x) ((const char*)(x)) /* will return (invalid) instead */
++const char *elf_strfmt(struct elf_binary *elf, elf_ptrval start);
++ /* like elf_strval but returns "(invalid)" instead of NULL */
+
+-#define elf_memcpy_safe(elf, dst, src, sz) memcpy((dst),(src),(sz))
+-#define elf_memset_safe(elf, dst, c, sz) memset((dst),(c),(sz))
++void elf_memcpy_safe(struct elf_binary*, elf_ptrval dst, elf_ptrval src, size_t);
++void elf_memset_safe(struct elf_binary*, elf_ptrval dst, int c, size_t);
+ /*
+- * Versions of memcpy and memset which will (in the next patch)
+- * arrange never to write outside permitted areas.
++ * Versions of memcpy and memset which arrange never to write
++ * outside permitted areas.
+ */
+
+-#define elf_store_val(elf, type, ptr, val) (*(type*)(ptr) = (val))
++int elf_access_ok(struct elf_binary * elf,
++ uint64_t ptrval, size_t size);
++
++#define elf_store_val(elf, type, ptr, val) \
++ ({ \
++ typeof(type) elf_store__val = (val); \
++ elf_ptrval elf_store__targ = ptr; \
++ if (elf_access_ok((elf), elf_store__targ, \
++ sizeof(elf_store__val))) { \
++ elf_memcpy_unchecked((void*)elf_store__targ, &elf_store__val, \
++ sizeof(elf_store__val)); \
++ } \
++ }) \
+ /* Stores a value at a particular PTRVAL. */
+
+-#define elf_store_field(elf, hdr, elm, val) \
+- (elf_store_val((elf), ELF__HANDLE_FIELD_TYPE(hdr, elm), \
+- &((hdr)->elm), \
++#define elf_store_field(elf, hdr, elm, val) \
++ (elf_store_val((elf), ELF__HANDLE_FIELD_TYPE(hdr, elm), \
++ ELF_HANDLE_PTRVAL(hdr) + ELF__HANDLE_FIELD_OFFSET(hdr, elm), \
+ (val)))
+ /* Stores a 32/64-bit field. hdr is a HANDLE and elm is the field name. */
+
+@@ -306,6 +356,10 @@ int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
+ /* xc_libelf_loader.c */
+
+ int elf_init(struct elf_binary *elf, const char *image, size_t size);
++ /*
++ * image and size must be correct. They will be recorded in
++ * *elf, and must remain valid while the elf is in use.
++ */
+ #ifdef __XEN__
+ void elf_set_verbose(struct elf_binary *elf);
+ #else
+@@ -321,6 +375,9 @@ uint64_t elf_lookup_addr(struct elf_binary *elf, const char *symbol);
+
+ void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart); /* private */
+
++void elf_mark_broken(struct elf_binary *elf, const char *msg);
++const char *elf_check_broken(const struct elf_binary *elf); /* NULL means OK */
++
+ /* ------------------------------------------------------------------------ */
+ /* xc_libelf_relocate.c */
+
+@@ -395,16 +452,33 @@ int elf_xen_parse_guest_info(struct elf_binary *elf,
+ int elf_xen_parse(struct elf_binary *elf,
+ struct elf_dom_parms *parms);
+
+-#define elf_memcpy_unchecked memcpy
+-#define elf_memset_unchecked memset
++static inline void *elf_memcpy_unchecked(void *dest, const void *src, size_t n)
++ { return memcpy(dest, src, n); }
++static inline void *elf_memmove_unchecked(void *dest, const void *src, size_t n)
++ { return memmove(dest, src, n); }
++static inline void *elf_memset_unchecked(void *s, int c, size_t n)
++ { return memset(s, c, n); }
+ /*
+- * Unsafe versions of memcpy and memset which take actual C
+- * pointers. These are just like real memcpy and memset.
++ * Unsafe versions of memcpy, memmove memset which take actual C
++ * pointers. These are just like the real functions.
++ * We provide these so that in libelf-private.h we can #define
++ * memcpy, memset and memmove to undefined MISTAKE things.
+ */
+
+
+-#define ELF_ADVANCE_DEST(elf, amount) elf->dest += (amount)
+- /* Advances past amount bytes of the current destination area. */
++/* Advances past amount bytes of the current destination area. */
++static inline void ELF_ADVANCE_DEST(struct elf_binary *elf, uint64_t amount)
++{
++ if ( elf->dest_size >= amount )
++ {
++ elf->dest_base += amount;
++ elf->dest_size -= amount;
++ }
++ else
++ {
++ elf->dest_size = 0;
++ }
++}
+
+
+ #endif /* __XEN_LIBELF_H__ */
+--
+1.7.2.5
+
diff --git a/xsa55-4.20011-libelf-Check-pointer-references-in-elf_is_elfbinary.patch b/xsa55-4.20011-libelf-Check-pointer-references-in-elf_is_elfbinary.patch
new file mode 100644
index 0000000..a91fac0
--- /dev/null
+++ b/xsa55-4.20011-libelf-Check-pointer-references-in-elf_is_elfbinary.patch
@@ -0,0 +1,108 @@
+From eb40af0a209a3778fe39737bb44fdc2b6d3c6b92 Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 24 May 2013 17:52:42 +0100
+Subject: [PATCH 11/16] libelf: Check pointer references in elf_is_elfbinary
+
+elf_is_elfbinary didn't take a length parameter and could potentially
+access out of range when provided with a very short image.
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+Acked-by: Ian Campbell <ian.campbell at citrix.com>
+Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk at oracle.com>
+
+v2: Style fix.
+ Fix commit message subject.
+---
+ tools/libxc/xc_dom_elfloader.c | 2 +-
+ xen/arch/x86/bzimage.c | 4 ++--
+ xen/common/libelf/libelf-loader.c | 2 +-
+ xen/common/libelf/libelf-tools.c | 9 ++++++---
+ xen/include/xen/libelf.h | 2 +-
+ 5 files changed, 11 insertions(+), 8 deletions(-)
+
+diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
+index 80152bf..92211bd 100644
+--- a/tools/libxc/xc_dom_elfloader.c
++++ b/tools/libxc/xc_dom_elfloader.c
+@@ -95,7 +95,7 @@ static int check_elf_kernel(struct xc_dom_image *dom, int verbose)
+ return -EINVAL;
+ }
+
+- if ( !elf_is_elfbinary(dom->kernel_blob) )
++ if ( !elf_is_elfbinary(dom->kernel_blob, dom->kernel_size) )
+ {
+ if ( verbose )
+ xc_dom_panic(dom->xch,
+diff --git a/xen/arch/x86/bzimage.c b/xen/arch/x86/bzimage.c
+index 5adc223..3600dca 100644
+--- a/xen/arch/x86/bzimage.c
++++ b/xen/arch/x86/bzimage.c
+@@ -220,7 +220,7 @@ unsigned long __init bzimage_headroom(char *image_start,
+ image_length = hdr->payload_length;
+ }
+
+- if ( elf_is_elfbinary(image_start) )
++ if ( elf_is_elfbinary(image_start, image_length) )
+ return 0;
+
+ orig_image_len = image_length;
+@@ -251,7 +251,7 @@ int __init bzimage_parse(char *image_base, char **image_start, unsigned long *im
+ *image_len = hdr->payload_length;
+ }
+
+- if ( elf_is_elfbinary(*image_start) )
++ if ( elf_is_elfbinary(*image_start, *image_len) )
+ return 0;
+
+ BUG_ON(!(image_base < *image_start));
+diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
+index a3310e7..f8be635 100644
+--- a/xen/common/libelf/libelf-loader.c
++++ b/xen/common/libelf/libelf-loader.c
+@@ -29,7 +29,7 @@ int elf_init(struct elf_binary *elf, const char *image_input, size_t size)
+ ELF_HANDLE_DECL(elf_shdr) shdr;
+ uint64_t i, count, section, offset;
+
+- if ( !elf_is_elfbinary(image_input) )
++ if ( !elf_is_elfbinary(image_input, size) )
+ {
+ elf_err(elf, "%s: not an ELF binary\n", __FUNCTION__);
+ return -1;
+diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
+index ed107bc..9c13377 100644
+--- a/xen/common/libelf/libelf-tools.c
++++ b/xen/common/libelf/libelf-tools.c
+@@ -329,11 +329,14 @@ ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(
+
+ /* ------------------------------------------------------------------------ */
+
+-int elf_is_elfbinary(const void *image)
++int elf_is_elfbinary(const void *image_start, size_t image_size)
+ {
+- const Elf32_Ehdr *ehdr = image;
++ const Elf32_Ehdr *ehdr = image_start;
+
+- return IS_ELF(*ehdr); /* fixme unchecked */
++ if ( image_size < sizeof(*ehdr) )
++ return 0;
++
++ return IS_ELF(*ehdr);
+ }
+
+ int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
+diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
+index bbde92e..12d77f9 100644
+--- a/xen/include/xen/libelf.h
++++ b/xen/include/xen/libelf.h
+@@ -349,7 +349,7 @@ uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
+ unsigned int unitsz, unsigned int idx);
+ ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
+
+-int elf_is_elfbinary(const void *image);
++int elf_is_elfbinary(const void *image_start, size_t image_size);
+ int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
+
+ /* ------------------------------------------------------------------------ */
+--
+1.7.2.5
+
diff --git a/xsa55-4.20012-libelf-Make-all-callers-call-elf_check_broken.patch b/xsa55-4.20012-libelf-Make-all-callers-call-elf_check_broken.patch
new file mode 100644
index 0000000..97b5cb4
--- /dev/null
+++ b/xsa55-4.20012-libelf-Make-all-callers-call-elf_check_broken.patch
@@ -0,0 +1,256 @@
+From 87c02b2160cbaf81c37b904d2e651bcdff149939 Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 24 May 2013 17:52:42 +0100
+Subject: [PATCH 12/16] libelf: Make all callers call elf_check_broken
+
+This arranges that if the new pointer reference error checking
+tripped, we actually get a message about it. In this patch these
+messages do not change the actual return values from the various
+functions: so pointer reference errors do not prevent loading. This
+is for fear that some existing kernels might cause the code to make
+these wild references, which would then break, which is not a good
+thing in a security patch.
+
+In xen/arch/x86/domain_build.c we have to introduce an "out" label and
+change all of the "return rc" beyond the relevant point into "goto
+out".
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+
+v3.1:
+ Add error check to xc_dom_parse_elf_kernel.
+ Move check in xc_hvm_build_x86.c:setup_guest to right place.
+
+v2 Acked-by: Ian Campbell <ian.campbell at citrix.com>
+v2 Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk at oracle.com>
+
+v2: Style fixes.
+---
+ tools/libxc/xc_dom_elfloader.c | 25 +++++++++++++++++++++----
+ tools/libxc/xc_hvm_build_x86.c | 5 +++++
+ tools/xcutils/readnotes.c | 3 +++
+ xen/arch/arm/kernel.c | 15 ++++++++++++++-
+ xen/arch/x86/domain_build.c | 28 +++++++++++++++++++++-------
+ 5 files changed, 64 insertions(+), 12 deletions(-)
+
+diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
+index 92211bd..c7958ec 100644
+--- a/tools/libxc/xc_dom_elfloader.c
++++ b/tools/libxc/xc_dom_elfloader.c
+@@ -277,6 +277,13 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+ elf_store_field(elf, shdr, e32.sh_name, 0);
+ }
+
++ if ( elf_check_broken(&syms) )
++ DOMPRINTF("%s: symbols ELF broken: %s", __FUNCTION__,
++ elf_check_broken(&syms));
++ if ( elf_check_broken(elf) )
++ DOMPRINTF("%s: ELF broken: %s", __FUNCTION__,
++ elf_check_broken(elf));
++
+ if ( tables == 0 )
+ {
+ DOMPRINTF("%s: no symbol table present", __FUNCTION__);
+@@ -313,19 +320,23 @@ static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
+ {
+ xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: ELF image"
+ " has no shstrtab", __FUNCTION__);
+- return -EINVAL;
++ rc = -EINVAL;
++ goto out;
+ }
+
+ /* parse binary and get xen meta info */
+ elf_parse_binary(elf);
+ if ( (rc = elf_xen_parse(elf, &dom->parms)) != 0 )
+- return rc;
++ {
++ goto out;
++ }
+
+ if ( elf_xen_feature_get(XENFEAT_dom0, dom->parms.f_required) )
+ {
+ xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: Kernel does not"
+ " support unprivileged (DomU) operation", __FUNCTION__);
+- return -EINVAL;
++ rc = -EINVAL;
++ goto out;
+ }
+
+ /* find kernel segment */
+@@ -339,7 +350,13 @@ static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
+ DOMPRINTF("%s: %s: 0x%" PRIx64 " -> 0x%" PRIx64 "",
+ __FUNCTION__, dom->guest_type,
+ dom->kernel_seg.vstart, dom->kernel_seg.vend);
+- return 0;
++ rc = 0;
++out:
++ if ( elf_check_broken(elf) )
++ DOMPRINTF("%s: ELF broken: %s", __FUNCTION__,
++ elf_check_broken(elf));
++
++ return rc;
+ }
+
+ static int xc_dom_load_elf_kernel(struct xc_dom_image *dom)
+diff --git a/tools/libxc/xc_hvm_build_x86.c b/tools/libxc/xc_hvm_build_x86.c
+index ccfd8b5..8165287 100644
+--- a/tools/libxc/xc_hvm_build_x86.c
++++ b/tools/libxc/xc_hvm_build_x86.c
+@@ -403,11 +403,16 @@ static int setup_guest(xc_interface *xch,
+ munmap(page0, PAGE_SIZE);
+ }
+
++ if ( elf_check_broken(&elf) )
++ ERROR("HVM ELF broken: %s", elf_check_broken(&elf));
++
+ free(page_array);
+ return 0;
+
+ error_out:
+ free(page_array);
++ if ( elf_check_broken(&elf) )
++ ERROR("HVM ELF broken, failing: %s", elf_check_broken(&elf));
+ return -1;
+ }
+
+diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
+index ca86ba5..b868fba 100644
+--- a/tools/xcutils/readnotes.c
++++ b/tools/xcutils/readnotes.c
+@@ -300,6 +300,9 @@ int main(int argc, char **argv)
+ printf("__xen_guest: %s\n",
+ elf_strfmt(&elf, elf_section_start(&elf, shdr)));
+
++ if (elf_check_broken(&elf))
++ printf("warning: broken ELF: %s\n", elf_check_broken(&elf));
++
+ return 0;
+ }
+
+diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c
+index 2d56130..dec0519 100644
+--- a/xen/arch/arm/kernel.c
++++ b/xen/arch/arm/kernel.c
+@@ -146,6 +146,8 @@ static int kernel_try_elf_prepare(struct kernel_info *info)
+ {
+ int rc;
+
++ memset(&info->elf.elf, 0, sizeof(info->elf.elf));
++
+ info->kernel_order = get_order_from_bytes(KERNEL_FLASH_SIZE);
+ info->kernel_img = alloc_xenheap_pages(info->kernel_order, 0);
+ if ( info->kernel_img == NULL )
+@@ -160,7 +162,7 @@ static int kernel_try_elf_prepare(struct kernel_info *info)
+ #endif
+ elf_parse_binary(&info->elf.elf);
+ if ( (rc = elf_xen_parse(&info->elf.elf, &info->elf.parms)) != 0 )
+- return rc;
++ goto err;
+
+ /*
+ * TODO: can the ELF header be used to find the physical address
+@@ -169,7 +171,18 @@ static int kernel_try_elf_prepare(struct kernel_info *info)
+ info->entry = info->elf.parms.virt_entry;
+ info->load = kernel_elf_load;
+
++ if ( elf_check_broken(&info->elf.elf) )
++ printk("Xen: warning: ELF kernel broken: %s\n",
++ elf_check_broken(&info->elf.elf));
++
+ return 0;
++
++err:
++ if ( elf_check_broken(&info->elf.elf) )
++ printk("Xen: ELF kernel broken: %s\n",
++ elf_check_broken(&info->elf.elf));
++
++ return rc;
+ }
+
+ int kernel_prepare(struct kernel_info *info)
+diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c
+index a655b21..0dbec96 100644
+--- a/xen/arch/x86/domain_build.c
++++ b/xen/arch/x86/domain_build.c
+@@ -374,7 +374,7 @@ int __init construct_dom0(
+ #endif
+ elf_parse_binary(&elf);
+ if ( (rc = elf_xen_parse(&elf, &parms)) != 0 )
+- return rc;
++ goto out;
+
+ /* compatibility check */
+ compatible = 0;
+@@ -413,14 +413,16 @@ int __init construct_dom0(
+ if ( !compatible )
+ {
+ printk("Mismatch between Xen and DOM0 kernel\n");
+- return -EINVAL;
++ rc = -EINVAL;
++ goto out;
+ }
+
+ if ( parms.elf_notes[XEN_ELFNOTE_SUPPORTED_FEATURES].type != XEN_ENT_NONE &&
+ !test_bit(XENFEAT_dom0, parms.f_supported) )
+ {
+ printk("Kernel does not support Dom0 operation\n");
+- return -EINVAL;
++ rc = -EINVAL;
++ goto out;
+ }
+
+ #if defined(__x86_64__)
+@@ -734,7 +736,8 @@ int __init construct_dom0(
+ (v_end > HYPERVISOR_COMPAT_VIRT_START(d)) )
+ {
+ printk("DOM0 image overlaps with Xen private area.\n");
+- return -EINVAL;
++ rc = -EINVAL;
++ goto out;
+ }
+
+ if ( is_pv_32on64_domain(d) )
+@@ -914,7 +917,7 @@ int __init construct_dom0(
+ if ( rc < 0 )
+ {
+ printk("Failed to load the kernel binary\n");
+- return rc;
++ goto out;
+ }
+ bootstrap_map(NULL);
+
+@@ -925,7 +928,8 @@ int __init construct_dom0(
+ {
+ write_ptbase(current);
+ printk("Invalid HYPERCALL_PAGE field in ELF notes.\n");
+- return -1;
++ rc = -1;
++ goto out;
+ }
+ hypercall_page_initialise(
+ d, (void *)(unsigned long)parms.virt_hypercall);
+@@ -1272,9 +1276,19 @@ int __init construct_dom0(
+
+ BUG_ON(rc != 0);
+
+- iommu_dom0_init(dom0);
++ if ( elf_check_broken(&elf) )
++ printk(" Xen warning: dom0 kernel broken ELF: %s\n",
++ elf_check_broken(&elf));
+
++ iommu_dom0_init(dom0);
+ return 0;
++
++out:
++ if ( elf_check_broken(&elf) )
++ printk(" Xen dom0 kernel broken ELF: %s\n",
++ elf_check_broken(&elf));
++
++ return rc;
+ }
+
+ /*
+--
+1.7.2.5
+
diff --git a/xsa55-4.20013-libelf-use-C99-bool-for-booleans.patch b/xsa55-4.20013-libelf-use-C99-bool-for-booleans.patch
new file mode 100644
index 0000000..e9c852b
--- /dev/null
+++ b/xsa55-4.20013-libelf-use-C99-bool-for-booleans.patch
@@ -0,0 +1,251 @@
+From ad1886e0b717d5455e57ac8c0556ddfac334f0e7 Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 24 May 2013 17:52:43 +0100
+Subject: [PATCH 13/16] libelf: use C99 bool for booleans
+
+We want to remove uses of "int" because signed integers have
+undesirable undefined behaviours on overflow. Malicious compilers can
+turn apparently-correct code into code with security vulnerabilities
+etc.
+
+In this patch we change all the booleans in libelf to C99 bool,
+from <stdbool.h>.
+
+For the one visible libelf boolean in libxc's public interface we
+retain the use of int to avoid changing the ABI; libxc converts it to
+a bool for consumption by libelf.
+
+It is OK to change all values only ever used as booleans to _Bool
+(bool) because conversion from any scalar type to a _Bool works the
+same as the boolean test in if() or ?: and is always defined (C99
+6.3.1.2). But we do need to check that all these variables really are
+only ever used that way. (It is theoretically possible that the old
+code truncated some 64-bit values to 32-bit ints which might become
+zero depending on the value, which would mean a behavioural change in
+this patch, but it seems implausible that treating 0x????????00000000
+as false could have been intended.)
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+
+v3: Use <stdbool.h>'s bool (or _Bool) instead of defining elf_bool.
+ Split this into a separate patch.
+---
+ tools/libxc/xc_dom_elfloader.c | 8 ++++----
+ xen/common/libelf/libelf-dominfo.c | 2 +-
+ xen/common/libelf/libelf-loader.c | 4 ++--
+ xen/common/libelf/libelf-private.h | 2 +-
+ xen/common/libelf/libelf-tools.c | 10 +++++-----
+ xen/include/xen/libelf.h | 18 ++++++++++--------
+ 6 files changed, 23 insertions(+), 21 deletions(-)
+
+diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
+index c7958ec..3738250 100644
+--- a/tools/libxc/xc_dom_elfloader.c
++++ b/tools/libxc/xc_dom_elfloader.c
+@@ -34,7 +34,7 @@
+ /* ------------------------------------------------------------------------ */
+
+ static void log_callback(struct elf_binary *elf, void *caller_data,
+- int iserr, const char *fmt, va_list al) {
++ bool iserr, const char *fmt, va_list al) {
+ xc_interface *xch = caller_data;
+
+ xc_reportv(xch,
+@@ -46,7 +46,7 @@ static void log_callback(struct elf_binary *elf, void *caller_data,
+
+ void xc_elf_set_logfile(xc_interface *xch, struct elf_binary *elf,
+ int verbose) {
+- elf_set_log(elf, log_callback, xch, verbose);
++ elf_set_log(elf, log_callback, xch, verbose /* convert to bool */);
+ }
+
+ /* ------------------------------------------------------------------------ */
+@@ -84,7 +84,7 @@ static char *xc_dom_guest_type(struct xc_dom_image *dom,
+ /* ------------------------------------------------------------------------ */
+ /* parse elf binary */
+
+-static int check_elf_kernel(struct xc_dom_image *dom, int verbose)
++static int check_elf_kernel(struct xc_dom_image *dom, bool verbose)
+ {
+ if ( dom->kernel_blob == NULL )
+ {
+@@ -112,7 +112,7 @@ static int xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
+ }
+
+ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+- struct elf_binary *elf, int load)
++ struct elf_binary *elf, bool load)
+ {
+ struct elf_binary syms;
+ ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr; ELF_HANDLE_DECL(elf_shdr) shdr2;
+diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
+index 98c80dc..12b6c2a 100644
+--- a/xen/common/libelf/libelf-dominfo.c
++++ b/xen/common/libelf/libelf-dominfo.c
+@@ -101,7 +101,7 @@ int elf_xen_parse_note(struct elf_binary *elf,
+ /* *INDENT-OFF* */
+ static const struct {
+ char *name;
+- int str;
++ bool str;
+ } note_desc[] = {
+ [XEN_ELFNOTE_ENTRY] = { "ENTRY", 0},
+ [XEN_ELFNOTE_HYPERCALL_PAGE] = { "HYPERCALL_PAGE", 0},
+diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
+index f8be635..0dccd4d 100644
+--- a/xen/common/libelf/libelf-loader.c
++++ b/xen/common/libelf/libelf-loader.c
+@@ -92,7 +92,7 @@ int elf_init(struct elf_binary *elf, const char *image_input, size_t size)
+ }
+
+ #ifndef __XEN__
+-void elf_call_log_callback(struct elf_binary *elf, int iserr,
++void elf_call_log_callback(struct elf_binary *elf, bool iserr,
+ const char *fmt,...) {
+ va_list al;
+
+@@ -107,7 +107,7 @@ void elf_call_log_callback(struct elf_binary *elf, int iserr,
+ }
+
+ void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
+- void *log_caller_data, int verbose)
++ void *log_caller_data, bool verbose)
+ {
+ elf->log_callback = log_callback;
+ elf->log_caller_data = log_caller_data;
+diff --git a/xen/common/libelf/libelf-private.h b/xen/common/libelf/libelf-private.h
+index 280dfd1..277be04 100644
+--- a/xen/common/libelf/libelf-private.h
++++ b/xen/common/libelf/libelf-private.h
+@@ -77,7 +77,7 @@
+ #define elf_err(elf, fmt, args ... ) \
+ elf_call_log_callback(elf, 1, fmt , ## args );
+
+-void elf_call_log_callback(struct elf_binary*, int iserr, const char *fmt,...);
++void elf_call_log_callback(struct elf_binary*, bool iserr, const char *fmt,...);
+
+ #define safe_strcpy(d,s) \
+ do { strncpy((d),(s),sizeof((d))-1); \
+diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
+index 9c13377..ac6438f 100644
+--- a/xen/common/libelf/libelf-tools.c
++++ b/xen/common/libelf/libelf-tools.c
+@@ -31,7 +31,7 @@ const char *elf_check_broken(const struct elf_binary *elf)
+ return elf->broken;
+ }
+
+-static int elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
++static bool elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
+ const void *region, uint64_t regionsize)
+ /*
+ * Returns true if the putative memory area [ptrval,ptrval+size>
+@@ -50,7 +50,7 @@ static int elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
+ return 1;
+ }
+
+-int elf_access_ok(struct elf_binary * elf,
++bool elf_access_ok(struct elf_binary * elf,
+ uint64_t ptrval, size_t size)
+ {
+ if ( elf_ptrval_in_range(ptrval, size, elf->image_base, elf->size) )
+@@ -89,7 +89,7 @@ uint64_t elf_access_unsigned(struct elf_binary * elf, elf_ptrval base,
+ uint64_t moreoffset, size_t size)
+ {
+ elf_ptrval ptrval = base + moreoffset;
+- int need_swap = elf_swap(elf);
++ bool need_swap = elf_swap(elf);
+ const uint8_t *u8;
+ const uint16_t *u16;
+ const uint32_t *u32;
+@@ -329,7 +329,7 @@ ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(
+
+ /* ------------------------------------------------------------------------ */
+
+-int elf_is_elfbinary(const void *image_start, size_t image_size)
++bool elf_is_elfbinary(const void *image_start, size_t image_size)
+ {
+ const Elf32_Ehdr *ehdr = image_start;
+
+@@ -339,7 +339,7 @@ int elf_is_elfbinary(const void *image_start, size_t image_size)
+ return IS_ELF(*ehdr);
+ }
+
+-int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
++bool elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
+ {
+ uint64_t p_type = elf_uval(elf, phdr, p_type);
+ uint64_t p_flags = elf_uval(elf, phdr, p_flags);
+diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
+index 12d77f9..22febea 100644
+--- a/xen/include/xen/libelf.h
++++ b/xen/include/xen/libelf.h
+@@ -29,6 +29,8 @@
+ #error define architectural endianness
+ #endif
+
++#include <stdbool.h>
++
+ #undef ELFSIZE
+ #include "elfstructs.h"
+ #ifdef __XEN__
+@@ -42,7 +44,7 @@
+
+ struct elf_binary;
+ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
+- int iserr, const char *fmt, va_list al);
++ bool iserr, const char *fmt, va_list al);
+
+ #endif
+
+@@ -236,7 +238,7 @@ struct elf_binary {
+ elf_log_callback *log_callback;
+ void *log_caller_data;
+ #endif
+- int verbose;
++ bool verbose;
+ const char *broken;
+ };
+
+@@ -300,8 +302,8 @@ void elf_memset_safe(struct elf_binary*, elf_ptrval dst, int c, size_t);
+ * outside permitted areas.
+ */
+
+-int elf_access_ok(struct elf_binary * elf,
+- uint64_t ptrval, size_t size);
++bool elf_access_ok(struct elf_binary * elf,
++ uint64_t ptrval, size_t size);
+
+ #define elf_store_val(elf, type, ptr, val) \
+ ({ \
+@@ -349,8 +351,8 @@ uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
+ unsigned int unitsz, unsigned int idx);
+ ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
+
+-int elf_is_elfbinary(const void *image_start, size_t image_size);
+-int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
++bool elf_is_elfbinary(const void *image_start, size_t image_size);
++bool elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
+
+ /* ------------------------------------------------------------------------ */
+ /* xc_libelf_loader.c */
+@@ -364,7 +366,7 @@ int elf_init(struct elf_binary *elf, const char *image, size_t size);
+ void elf_set_verbose(struct elf_binary *elf);
+ #else
+ void elf_set_log(struct elf_binary *elf, elf_log_callback*,
+- void *log_caller_pointer, int verbose);
++ void *log_caller_pointer, bool verbose);
+ #endif
+
+ void elf_parse_binary(struct elf_binary *elf);
+@@ -416,7 +418,7 @@ struct elf_dom_parms {
+ char xen_ver[16];
+ char loader[16];
+ int pae;
+- int bsd_symtab;
++ bool bsd_symtab;
+ uint64_t virt_base;
+ uint64_t virt_entry;
+ uint64_t virt_hypercall;
+--
+1.7.2.5
+
diff --git a/xsa55-4.20014-libelf-use-only-unsigned-integers.patch b/xsa55-4.20014-libelf-use-only-unsigned-integers.patch
new file mode 100644
index 0000000..361cce8
--- /dev/null
+++ b/xsa55-4.20014-libelf-use-only-unsigned-integers.patch
@@ -0,0 +1,765 @@
+From 2238fd744ab359dc82e6299629fdf442a197bee3 Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 24 May 2013 17:52:43 +0100
+Subject: [PATCH 14/16] libelf: use only unsigned integers
+
+Signed integers have undesirable undefined behaviours on overflow.
+Malicious compilers can turn apparently-correct code into code with
+security vulnerabilities etc.
+
+So use only unsigned integers. Exceptions are booleans (which we have
+already changed) and error codes.
+
+We _do_ change all the chars which aren't fixed constants from our own
+text segment, but not the char*s. This is because it is safe to
+access an arbitrary byte through a char*, but not necessarily safe to
+convert an arbitrary value to a char.
+
+As a consequence we need to compile libelf with -Wno-pointer-sign.
+
+It is OK to change all the signed integers to unsigned because all the
+inequalities in libelf are in contexts where we don't "expect"
+negative numbers.
+
+In libelf-dominfo.c:elf_xen_parse we rename a variable "rc" to
+"more_notes" as it actually contains a note count derived from the
+input image. The "error" return value from elf_xen_parse_notes is
+changed from -1 to ~0U.
+
+grepping shows only one occurrence of "PRId" or "%d" or "%ld" in
+libelf and xc_dom_elfloader.c (a "%d" which becomes "%u").
+
+For those concerned about unintentional functional changes, the
+following rune produces a version of the patch which is much smaller
+and eliminates only non-functional changes:
+
+ GIT_EXTERNAL_DIFF=.../unsigned-differ git-diff <before>..<after>
+
+where <before> and <after> are git refs for the code before and after
+this patch, and unsigned-differ is this shell script:
+
+ #!/bin/bash
+ set -e
+
+ seddery () {
+ perl -pe 's/\b(?:elf_errorstatus|elf_negerrnoval)\b/int/g'
+ }
+
+ path="$1"
+ in="$2"
+ out="$5"
+
+ set +e
+ diff -pu --label "$path~" <(seddery <"$in") --label "$path" <(seddery <"$out")
+ rc=$?
+ set -e
+ if [ $rc = 1 ]; then rc=0; fi
+ exit $rc
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+
+v3: Changes to booleans split off into separate patch.
+
+v2: BUGFIX: Eliminate conversion to int of return from elf_xen_parse_notes.
+ BUGFIX: Fix the one printf format thing which needs changing.
+ Remove irrelevant change to constify note_desc.name in libelf-dominfo.c.
+ In xc_dom_load_elf_symtab change one sizeof(int) to sizeof(unsigned).
+ Do not change type of 2nd argument to memset.
+ Provide seddery for easier review.
+ Style fix.
+---
+ tools/libxc/Makefile | 9 +++++-
+ tools/libxc/xc_dom.h | 7 +++--
+ tools/libxc/xc_dom_elfloader.c | 42 ++++++++++++++++-------------
+ tools/xcutils/readnotes.c | 15 ++++++-----
+ xen/common/libelf/Makefile | 2 +
+ xen/common/libelf/libelf-dominfo.c | 50 ++++++++++++++++++------------------
+ xen/common/libelf/libelf-loader.c | 20 +++++++-------
+ xen/common/libelf/libelf-tools.c | 24 ++++++++--------
+ xen/include/xen/libelf.h | 21 ++++++++------
+ 9 files changed, 103 insertions(+), 87 deletions(-)
+
+diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
+index d8c6a60..a3fd90c 100644
+--- a/tools/libxc/Makefile
++++ b/tools/libxc/Makefile
+@@ -52,8 +52,13 @@ endif
+ 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
++ELF_SRCS-y += libelf-tools.c libelf-loader.c
++ELF_SRCS-y += libelf-dominfo.c
++
++GUEST_SRCS-y += $(ELF_SRCS-y)
++
++$(patsubst %.c,%.o,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign
++$(patsubst %.c,%.opic,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign
+
+ # new domain builder
+ GUEST_SRCS-y += xc_dom_core.c xc_dom_boot.c
+diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h
+index b74252f..eb02c25 100644
+--- a/tools/libxc/xc_dom.h
++++ b/tools/libxc/xc_dom.h
+@@ -140,9 +140,10 @@ struct xc_dom_image {
+
+ struct xc_dom_loader {
+ char *name;
+- int (*probe) (struct xc_dom_image * dom);
+- int (*parser) (struct xc_dom_image * dom);
+- int (*loader) (struct xc_dom_image * dom);
++ /* Sadly the error returns from these functions are not consistent: */
++ elf_negerrnoval (*probe) (struct xc_dom_image * dom);
++ elf_negerrnoval (*parser) (struct xc_dom_image * dom);
++ elf_errorstatus (*loader) (struct xc_dom_image * dom);
+
+ struct xc_dom_loader *next;
+ };
+diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
+index 3738250..d9b1a43 100644
+--- a/tools/libxc/xc_dom_elfloader.c
++++ b/tools/libxc/xc_dom_elfloader.c
+@@ -84,7 +84,7 @@ static char *xc_dom_guest_type(struct xc_dom_image *dom,
+ /* ------------------------------------------------------------------------ */
+ /* parse elf binary */
+
+-static int check_elf_kernel(struct xc_dom_image *dom, bool verbose)
++static elf_negerrnoval check_elf_kernel(struct xc_dom_image *dom, bool verbose)
+ {
+ if ( dom->kernel_blob == NULL )
+ {
+@@ -106,12 +106,12 @@ static int check_elf_kernel(struct xc_dom_image *dom, bool verbose)
+ return 0;
+ }
+
+-static int xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
++static elf_negerrnoval xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
+ {
+ return check_elf_kernel(dom, 0);
+ }
+
+-static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
++static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+ struct elf_binary *elf, bool load)
+ {
+ struct elf_binary syms;
+@@ -119,7 +119,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+ xen_vaddr_t symtab, maxaddr;
+ ELF_PTRVAL_CHAR hdr;
+ size_t size;
+- int h, count, type, i, tables = 0;
++ unsigned h, count, type, i, tables = 0;
+ unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
+
+ if ( elf_swap(elf) )
+@@ -141,13 +141,13 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+ elf->caller_xdest_size = page_size -
+ (dom->bsd_symtab_start & (page_size-1));
+ hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
+- elf_store_val(elf, int, hdr, size - sizeof(int));
++ elf_store_val(elf, unsigned, hdr, size - sizeof(unsigned));
+ }
+ else
+ {
+ char *hdr_ptr;
+
+- size = sizeof(int) + elf_size(elf, elf->ehdr) +
++ size = sizeof(unsigned) + elf_size(elf, elf->ehdr) +
+ elf_shdr_count(elf) * elf_size(elf, shdr);
+ hdr_ptr = xc_dom_malloc(dom, size);
+ if ( hdr_ptr == NULL )
+@@ -158,15 +158,15 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+ dom->bsd_symtab_start = elf_round_up(elf, dom->kernel_seg.vend);
+ }
+
+- elf_memcpy_safe(elf, hdr + sizeof(int),
++ elf_memcpy_safe(elf, hdr + sizeof(unsigned),
+ ELF_IMAGE_BASE(elf),
+ elf_size(elf, elf->ehdr));
+- elf_memcpy_safe(elf, hdr + sizeof(int) + elf_size(elf, elf->ehdr),
++ elf_memcpy_safe(elf, hdr + sizeof(unsigned) + elf_size(elf, elf->ehdr),
+ ELF_IMAGE_BASE(elf) + elf_uval(elf, elf->ehdr, e_shoff),
+ elf_shdr_count(elf) * elf_size(elf, shdr));
+ if ( elf_64bit(elf) )
+ {
+- Elf64_Ehdr *ehdr = (Elf64_Ehdr *)(hdr + sizeof(int));
++ Elf64_Ehdr *ehdr = (Elf64_Ehdr *)(hdr + sizeof(unsigned));
+ ehdr->e_phoff = 0;
+ ehdr->e_phentsize = 0;
+ ehdr->e_phnum = 0;
+@@ -175,22 +175,22 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+ }
+ else
+ {
+- Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(hdr + sizeof(int));
++ Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(hdr + sizeof(unsigned));
+ ehdr->e_phoff = 0;
+ ehdr->e_phentsize = 0;
+ ehdr->e_phnum = 0;
+ ehdr->e_shoff = elf_size(elf, elf->ehdr);
+ ehdr->e_shstrndx = SHN_UNDEF;
+ }
+- if ( elf->caller_xdest_size < sizeof(int) )
++ if ( elf->caller_xdest_size < sizeof(unsigned) )
+ {
+ DOMPRINTF("%s/%s: header size %"PRIx64" too small",
+ __FUNCTION__, load ? "load" : "parse",
+ (uint64_t)elf->caller_xdest_size);
+ return -1;
+ }
+- if ( elf_init(&syms, elf->caller_xdest_base + sizeof(int),
+- elf->caller_xdest_size - sizeof(int)) )
++ if ( elf_init(&syms, elf->caller_xdest_base + sizeof(unsigned),
++ elf->caller_xdest_size - sizeof(unsigned)) )
+ return -1;
+
+ /*
+@@ -210,7 +210,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+
+ xc_elf_set_logfile(dom->xch, &syms, 1);
+
+- symtab = dom->bsd_symtab_start + sizeof(int);
++ symtab = dom->bsd_symtab_start + sizeof(unsigned);
+ maxaddr = elf_round_up(&syms, symtab + elf_size(&syms, syms.ehdr) +
+ elf_shdr_count(&syms) * elf_size(&syms, shdr));
+
+@@ -256,7 +256,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+ size = elf_uval(&syms, shdr, sh_size);
+ maxaddr = elf_round_up(&syms, maxaddr + size);
+ tables++;
+- DOMPRINTF("%s: h=%d %s, size=0x%zx, maxaddr=0x%" PRIx64 "",
++ DOMPRINTF("%s: h=%u %s, size=0x%zx, maxaddr=0x%" PRIx64 "",
+ __FUNCTION__, h,
+ type == SHT_SYMTAB ? "symtab" : "strtab",
+ size, maxaddr);
+@@ -295,10 +295,14 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+ return 0;
+ }
+
+-static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
++static elf_errorstatus xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
++ /*
++ * This function sometimes returns -1 for error and sometimes
++ * an errno value. WTF?
++ */
+ {
+ struct elf_binary *elf;
+- int rc;
++ elf_errorstatus rc;
+
+ rc = check_elf_kernel(dom, 1);
+ if ( rc != 0 )
+@@ -359,10 +363,10 @@ out:
+ return rc;
+ }
+
+-static int xc_dom_load_elf_kernel(struct xc_dom_image *dom)
++static elf_errorstatus xc_dom_load_elf_kernel(struct xc_dom_image *dom)
+ {
+ struct elf_binary *elf = dom->private_loader;
+- int rc;
++ elf_errorstatus rc;
+ xen_pfn_t pages;
+
+ elf->dest_base = xc_dom_seg_to_ptr_pages(dom, &dom->kernel_seg, &pages);
+diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
+index b868fba..9be1594 100644
+--- a/tools/xcutils/readnotes.c
++++ b/tools/xcutils/readnotes.c
+@@ -70,7 +70,7 @@ static void print_numeric_note(const char *prefix, struct elf_binary *elf,
+ ELF_HANDLE_DECL(elf_note) note)
+ {
+ uint64_t value = elf_note_numeric(elf, note);
+- int descsz = elf_uval(elf, note, descsz);
++ unsigned descsz = elf_uval(elf, note, descsz);
+
+ printf("%s: %#*" PRIx64 " (%d bytes)\n",
+ prefix, 2+2*descsz, value, descsz);
+@@ -79,7 +79,7 @@ static void print_numeric_note(const char *prefix, struct elf_binary *elf,
+ static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf,
+ ELF_HANDLE_DECL(elf_note) note)
+ {
+- int descsz = elf_uval(elf, note, descsz);
++ unsigned descsz = elf_uval(elf, note, descsz);
+ ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
+
+ /* XXX should be able to cope with a list of values. */
+@@ -99,10 +99,10 @@ static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf,
+
+ }
+
+-static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start, ELF_HANDLE_DECL(elf_note) end)
++static unsigned print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start, ELF_HANDLE_DECL(elf_note) end)
+ {
+ ELF_HANDLE_DECL(elf_note) note;
+- int notes_found = 0;
++ unsigned notes_found = 0;
+ const char *this_note_name;
+
+ for ( note = start; ELF_HANDLE_PTRVAL(note) < ELF_HANDLE_PTRVAL(end); note = elf_note_next(elf, note) )
+@@ -160,7 +160,7 @@ static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start,
+ break;
+ default:
+ printf("unknown note type %#x\n",
+- (int)elf_uval(elf, note, type));
++ (unsigned)elf_uval(elf, note, type));
+ break;
+ }
+ }
+@@ -170,12 +170,13 @@ static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start,
+ int main(int argc, char **argv)
+ {
+ const char *f;
+- int fd,h,size,usize,count;
++ int fd;
++ unsigned h,size,usize,count;
+ void *image,*tmp;
+ struct stat st;
+ struct elf_binary elf;
+ ELF_HANDLE_DECL(elf_shdr) shdr;
+- int notes_found = 0;
++ unsigned notes_found = 0;
+
+ struct setup_header *hdr;
+ uint64_t payload_offset, payload_length;
+diff --git a/xen/common/libelf/Makefile b/xen/common/libelf/Makefile
+index 18dc8e2..5bf8f76 100644
+--- a/xen/common/libelf/Makefile
++++ b/xen/common/libelf/Makefile
+@@ -2,6 +2,8 @@ obj-bin-y := libelf.o
+
+ SECTIONS := text data $(SPECIAL_DATA_SECTIONS)
+
++CFLAGS += -Wno-pointer-sign
++
+ libelf.o: libelf-temp.o Makefile
+ $(OBJCOPY) $(foreach s,$(SECTIONS),--rename-section .$(s)=.init.$(s)) $< $@
+
+diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
+index 12b6c2a..e837d4d 100644
+--- a/xen/common/libelf/libelf-dominfo.c
++++ b/xen/common/libelf/libelf-dominfo.c
+@@ -29,15 +29,15 @@ static const char *const elf_xen_feature_names[] = {
+ [XENFEAT_pae_pgdir_above_4gb] = "pae_pgdir_above_4gb",
+ [XENFEAT_dom0] = "dom0"
+ };
+-static const int elf_xen_features =
++static const unsigned elf_xen_features =
+ sizeof(elf_xen_feature_names) / sizeof(elf_xen_feature_names[0]);
+
+-int elf_xen_parse_features(const char *features,
++elf_errorstatus elf_xen_parse_features(const char *features,
+ uint32_t *supported,
+ uint32_t *required)
+ {
+- char feature[64];
+- int pos, len, i;
++ unsigned char feature[64];
++ unsigned pos, len, i;
+
+ if ( features == NULL )
+ return 0;
+@@ -94,7 +94,7 @@ int elf_xen_parse_features(const char *features,
+ /* ------------------------------------------------------------------------ */
+ /* xen elf notes */
+
+-int elf_xen_parse_note(struct elf_binary *elf,
++elf_errorstatus elf_xen_parse_note(struct elf_binary *elf,
+ struct elf_dom_parms *parms,
+ ELF_HANDLE_DECL(elf_note) note)
+ {
+@@ -125,7 +125,7 @@ int elf_xen_parse_note(struct elf_binary *elf,
+ const char *str = NULL;
+ uint64_t val = 0;
+ unsigned int i;
+- int type = elf_uval(elf, note, type);
++ unsigned type = elf_uval(elf, note, type);
+
+ if ( (type >= sizeof(note_desc) / sizeof(note_desc[0])) ||
+ (note_desc[type].name == NULL) )
+@@ -216,12 +216,12 @@ int elf_xen_parse_note(struct elf_binary *elf,
+ return 0;
+ }
+
+-static int elf_xen_parse_notes(struct elf_binary *elf,
++static unsigned elf_xen_parse_notes(struct elf_binary *elf,
+ struct elf_dom_parms *parms,
+ ELF_PTRVAL_CONST_VOID start,
+ ELF_PTRVAL_CONST_VOID end)
+ {
+- int xen_elfnotes = 0;
++ unsigned xen_elfnotes = 0;
+ ELF_HANDLE_DECL(elf_note) note;
+ const char *note_name;
+
+@@ -237,7 +237,7 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
+ if ( strcmp(note_name, "Xen") )
+ continue;
+ if ( elf_xen_parse_note(elf, parms, note) )
+- return -1;
++ return ~0U;
+ xen_elfnotes++;
+ }
+ return xen_elfnotes;
+@@ -246,12 +246,12 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
+ /* ------------------------------------------------------------------------ */
+ /* __xen_guest section */
+
+-int elf_xen_parse_guest_info(struct elf_binary *elf,
++elf_errorstatus elf_xen_parse_guest_info(struct elf_binary *elf,
+ struct elf_dom_parms *parms)
+ {
+ ELF_PTRVAL_CONST_CHAR h;
+- char name[32], value[128];
+- int len;
++ unsigned char name[32], value[128];
++ unsigned len;
+
+ h = parms->guest_info;
+ #define STAR(h) (elf_access_unsigned(elf, (h), 0, 1))
+@@ -334,13 +334,13 @@ int elf_xen_parse_guest_info(struct elf_binary *elf,
+ /* ------------------------------------------------------------------------ */
+ /* sanity checks */
+
+-static int elf_xen_note_check(struct elf_binary *elf,
++static elf_errorstatus elf_xen_note_check(struct elf_binary *elf,
+ struct elf_dom_parms *parms)
+ {
+ if ( (ELF_PTRVAL_INVALID(parms->elf_note_start)) &&
+ (ELF_PTRVAL_INVALID(parms->guest_info)) )
+ {
+- int machine = elf_uval(elf, elf->ehdr, e_machine);
++ unsigned machine = elf_uval(elf, elf->ehdr, e_machine);
+ if ( (machine == EM_386) || (machine == EM_X86_64) )
+ {
+ elf_err(elf, "%s: ERROR: Not a Xen-ELF image: "
+@@ -378,7 +378,7 @@ static int elf_xen_note_check(struct elf_binary *elf,
+ return 0;
+ }
+
+-static int elf_xen_addr_calc_check(struct elf_binary *elf,
++static elf_errorstatus elf_xen_addr_calc_check(struct elf_binary *elf,
+ struct elf_dom_parms *parms)
+ {
+ if ( (parms->elf_paddr_offset != UNSET_ADDR) &&
+@@ -464,13 +464,13 @@ static int elf_xen_addr_calc_check(struct elf_binary *elf,
+ /* ------------------------------------------------------------------------ */
+ /* glue it all together ... */
+
+-int elf_xen_parse(struct elf_binary *elf,
++elf_errorstatus elf_xen_parse(struct elf_binary *elf,
+ struct elf_dom_parms *parms)
+ {
+ ELF_HANDLE_DECL(elf_shdr) shdr;
+ ELF_HANDLE_DECL(elf_phdr) phdr;
+- int xen_elfnotes = 0;
+- int i, count, rc;
++ unsigned xen_elfnotes = 0;
++ unsigned i, count, more_notes;
+
+ elf_memset_unchecked(parms, 0, sizeof(*parms));
+ parms->virt_base = UNSET_ADDR;
+@@ -495,13 +495,13 @@ int elf_xen_parse(struct elf_binary *elf,
+ if (elf_uval(elf, phdr, p_offset) == 0)
+ continue;
+
+- rc = elf_xen_parse_notes(elf, parms,
++ more_notes = elf_xen_parse_notes(elf, parms,
+ elf_segment_start(elf, phdr),
+ elf_segment_end(elf, phdr));
+- if ( rc == -1 )
++ if ( more_notes == ~0U )
+ return -1;
+
+- xen_elfnotes += rc;
++ xen_elfnotes += more_notes;
+ }
+
+ /*
+@@ -518,17 +518,17 @@ int elf_xen_parse(struct elf_binary *elf,
+ if ( elf_uval(elf, shdr, sh_type) != SHT_NOTE )
+ continue;
+
+- rc = elf_xen_parse_notes(elf, parms,
++ more_notes = elf_xen_parse_notes(elf, parms,
+ elf_section_start(elf, shdr),
+ elf_section_end(elf, shdr));
+
+- if ( rc == -1 )
++ if ( more_notes == ~0U )
+ return -1;
+
+- if ( xen_elfnotes == 0 && rc > 0 )
++ if ( xen_elfnotes == 0 && more_notes > 0 )
+ elf_msg(elf, "%s: using notes from SHT_NOTE section\n", __FUNCTION__);
+
+- xen_elfnotes += rc;
++ xen_elfnotes += more_notes;
+ }
+
+ }
+diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
+index 0dccd4d..c3a9e51 100644
+--- a/xen/common/libelf/libelf-loader.c
++++ b/xen/common/libelf/libelf-loader.c
+@@ -24,7 +24,7 @@
+
+ /* ------------------------------------------------------------------------ */
+
+-int elf_init(struct elf_binary *elf, const char *image_input, size_t size)
++elf_errorstatus elf_init(struct elf_binary *elf, const char *image_input, size_t size)
+ {
+ ELF_HANDLE_DECL(elf_shdr) shdr;
+ uint64_t i, count, section, offset;
+@@ -114,7 +114,7 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
+ elf->verbose = verbose;
+ }
+
+-static int elf_load_image(struct elf_binary *elf,
++static elf_errorstatus elf_load_image(struct elf_binary *elf,
+ ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src,
+ uint64_t filesz, uint64_t memsz)
+ {
+@@ -129,9 +129,9 @@ void elf_set_verbose(struct elf_binary *elf)
+ elf->verbose = 1;
+ }
+
+-static int elf_load_image(struct elf_binary *elf, ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src, uint64_t filesz, uint64_t memsz)
++static elf_errorstatus elf_load_image(struct elf_binary *elf, ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src, uint64_t filesz, uint64_t memsz)
+ {
+- int rc;
++ elf_errorstatus rc;
+ if ( filesz > ULONG_MAX || memsz > ULONG_MAX )
+ return -1;
+ /* We trust the dom0 kernel image completely, so we don't care
+@@ -151,7 +151,7 @@ void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart)
+ {
+ uint64_t sz;
+ ELF_HANDLE_DECL(elf_shdr) shdr;
+- int i, type;
++ unsigned i, type;
+
+ if ( !ELF_HANDLE_VALID(elf->sym_tab) )
+ return;
+@@ -187,7 +187,7 @@ static void elf_load_bsdsyms(struct elf_binary *elf)
+ ELF_PTRVAL_VOID symbase;
+ ELF_PTRVAL_VOID symtab_addr;
+ ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr;
+- int i, type;
++ unsigned i, type;
+
+ if ( !elf->bsd_symtab_pstart )
+ return;
+@@ -220,7 +220,7 @@ do { \
+ elf_memcpy_safe(elf, ELF_HANDLE_PTRVAL(shdr),
+ ELF_IMAGE_BASE(elf) + elf_uval(elf, elf->ehdr, e_shoff),
+ sz);
+- maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (long)maxva + sz);
++ maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (unsigned long)maxva + sz);
+
+ for ( i = 0; i < elf_shdr_count(elf); i++ )
+ {
+@@ -233,10 +233,10 @@ do { \
+ elf_memcpy_safe(elf, maxva, elf_section_start(elf, shdr), sz);
+ /* Mangled to be based on ELF header location. */
+ elf_hdr_elm(elf, shdr, sh_offset, maxva - symtab_addr);
+- maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (long)maxva + sz);
++ maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (unsigned long)maxva + sz);
+ }
+ shdr = ELF_MAKE_HANDLE(elf_shdr, ELF_HANDLE_PTRVAL(shdr) +
+- (long)elf_uval(elf, elf->ehdr, e_shentsize));
++ (unsigned long)elf_uval(elf, elf->ehdr, e_shentsize));
+ }
+
+ /* Write down the actual sym size. */
+@@ -273,7 +273,7 @@ void elf_parse_binary(struct elf_binary *elf)
+ __FUNCTION__, elf->pstart, elf->pend);
+ }
+
+-int elf_load_binary(struct elf_binary *elf)
++elf_errorstatus elf_load_binary(struct elf_binary *elf)
+ {
+ ELF_HANDLE_DECL(elf_phdr) phdr;
+ uint64_t i, count, paddr, offset, filesz, memsz;
+diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
+index ac6438f..308ea15 100644
+--- a/xen/common/libelf/libelf-tools.c
++++ b/xen/common/libelf/libelf-tools.c
+@@ -119,19 +119,19 @@ uint64_t elf_access_unsigned(struct elf_binary * elf, elf_ptrval base,
+
+ uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr)
+ {
+- int elf_round = (elf_64bit(elf) ? 8 : 4) - 1;
++ unsigned elf_round = (elf_64bit(elf) ? 8 : 4) - 1;
+
+ return (addr + elf_round) & ~elf_round;
+ }
+
+ /* ------------------------------------------------------------------------ */
+
+-int elf_shdr_count(struct elf_binary *elf)
++unsigned elf_shdr_count(struct elf_binary *elf)
+ {
+ return elf_uval(elf, elf->ehdr, e_shnum);
+ }
+
+-int elf_phdr_count(struct elf_binary *elf)
++unsigned elf_phdr_count(struct elf_binary *elf)
+ {
+ return elf_uval(elf, elf->ehdr, e_phnum);
+ }
+@@ -141,7 +141,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
+ uint64_t count = elf_shdr_count(elf);
+ ELF_HANDLE_DECL(elf_shdr) shdr;
+ const char *sname;
+- int i;
++ unsigned i;
+
+ for ( i = 0; i < count; i++ )
+ {
+@@ -153,7 +153,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
+ return ELF_INVALID_HANDLE(elf_shdr);
+ }
+
+-ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index)
++ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, unsigned index)
+ {
+ uint64_t count = elf_shdr_count(elf);
+ ELF_PTRVAL_CONST_VOID ptr;
+@@ -167,7 +167,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index)
+ return ELF_MAKE_HANDLE(elf_shdr, ptr);
+ }
+
+-ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, int index)
++ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, unsigned index)
+ {
+ uint64_t count = elf_uval(elf, elf->ehdr, e_phnum);
+ ELF_PTRVAL_CONST_VOID ptr;
+@@ -261,7 +261,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym
+ return ELF_INVALID_HANDLE(elf_sym);
+ }
+
+-ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index)
++ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, unsigned index)
+ {
+ ELF_PTRVAL_CONST_VOID ptr = elf_section_start(elf, elf->sym_tab);
+ ELF_HANDLE_DECL(elf_sym) sym;
+@@ -277,7 +277,7 @@ const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note
+
+ ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
+ {
+- int namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
++ unsigned namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
+
+ return ELF_HANDLE_PTRVAL(note) + elf_size(elf, note) + namesz;
+ }
+@@ -285,7 +285,7 @@ ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_
+ uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
+ {
+ ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
+- int descsz = elf_uval(elf, note, descsz);
++ unsigned descsz = elf_uval(elf, note, descsz);
+
+ switch (descsz)
+ {
+@@ -303,7 +303,7 @@ uint64_t elf_note_numeric_array(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note
+ unsigned int unitsz, unsigned int idx)
+ {
+ ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
+- int descsz = elf_uval(elf, note, descsz);
++ unsigned descsz = elf_uval(elf, note, descsz);
+
+ if ( descsz % unitsz || idx >= descsz / unitsz )
+ return 0;
+@@ -321,8 +321,8 @@ uint64_t elf_note_numeric_array(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note
+
+ ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
+ {
+- int namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
+- int descsz = (elf_uval(elf, note, descsz) + 3) & ~3;
++ unsigned namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
++ unsigned descsz = (elf_uval(elf, note, descsz) + 3) & ~3;
+
+ return ELF_MAKE_HANDLE(elf_note, ELF_HANDLE_PTRVAL(note) + elf_size(elf, note) + namesz + descsz);
+ }
+diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
+index 22febea..4fc2496 100644
+--- a/xen/include/xen/libelf.h
++++ b/xen/include/xen/libelf.h
+@@ -31,6 +31,9 @@
+
+ #include <stdbool.h>
+
++typedef int elf_errorstatus; /* 0: ok; -ve (normally -1): error */
++typedef int elf_negerrnoval; /* 0: ok; -EFOO: error */
++
+ #undef ELFSIZE
+ #include "elfstructs.h"
+ #ifdef __XEN__
+@@ -327,12 +330,12 @@ bool elf_access_ok(struct elf_binary * elf,
+ /* ------------------------------------------------------------------------ */
+ /* xc_libelf_tools.c */
+
+-int elf_shdr_count(struct elf_binary *elf);
+-int elf_phdr_count(struct elf_binary *elf);
++unsigned elf_shdr_count(struct elf_binary *elf);
++unsigned elf_phdr_count(struct elf_binary *elf);
+
+ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *name);
+-ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index);
+-ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, int index);
++ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, unsigned index);
++ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, unsigned index);
+
+ const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr); /* might return NULL if inputs are invalid */
+ ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
+@@ -342,7 +345,7 @@ ELF_PTRVAL_CONST_VOID elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(
+ ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
+
+ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol);
+-ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index);
++ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, unsigned index);
+
+ const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); /* may return NULL */
+ ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
+@@ -357,7 +360,7 @@ bool elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr
+ /* ------------------------------------------------------------------------ */
+ /* xc_libelf_loader.c */
+
+-int elf_init(struct elf_binary *elf, const char *image, size_t size);
++elf_errorstatus elf_init(struct elf_binary *elf, const char *image, size_t size);
+ /*
+ * image and size must be correct. They will be recorded in
+ * *elf, and must remain valid while the elf is in use.
+@@ -370,7 +373,7 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback*,
+ #endif
+
+ void elf_parse_binary(struct elf_binary *elf);
+-int elf_load_binary(struct elf_binary *elf);
++elf_errorstatus elf_load_binary(struct elf_binary *elf);
+
+ ELF_PTRVAL_VOID elf_get_ptr(struct elf_binary *elf, unsigned long addr);
+ uint64_t elf_lookup_addr(struct elf_binary *elf, const char *symbol);
+@@ -383,7 +386,7 @@ const char *elf_check_broken(const struct elf_binary *elf); /* NULL means OK */
+ /* ------------------------------------------------------------------------ */
+ /* xc_libelf_relocate.c */
+
+-int elf_reloc(struct elf_binary *elf);
++elf_errorstatus elf_reloc(struct elf_binary *elf);
+
+ /* ------------------------------------------------------------------------ */
+ /* xc_libelf_dominfo.c */
+@@ -417,7 +420,7 @@ struct elf_dom_parms {
+ char guest_ver[16];
+ char xen_ver[16];
+ char loader[16];
+- int pae;
++ int pae; /* some kind of enum apparently */
+ bool bsd_symtab;
+ uint64_t virt_base;
+ uint64_t virt_entry;
+--
+1.7.2.5
+
diff --git a/xsa55-4.20015-libelf-check-loops-for-running-away.patch b/xsa55-4.20015-libelf-check-loops-for-running-away.patch
new file mode 100644
index 0000000..9fed7c0
--- /dev/null
+++ b/xsa55-4.20015-libelf-check-loops-for-running-away.patch
@@ -0,0 +1,195 @@
+From e7b3dc915e427c784fbf52f1689c83b518053330 Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 24 May 2013 17:52:43 +0100
+Subject: [PATCH 15/16] libelf: check loops for running away
+
+Ensure that libelf does not have any loops which can run away
+indefinitely even if the input is bogus. (Grepped for \bfor, \bwhile
+and \bgoto in libelf and xc_dom_*loader*.c.)
+
+Changes needed:
+ * elf_note_next uses the note's unchecked alleged length, which might
+ wrap round. If it does, return ELF_MAX_PTRVAL (0xfff..fff) instead,
+ which will be beyond the end of the section and so terminate the
+ caller's loop.
+ * In various loops over section and program headers, check that the
+ calculated header pointer is still within the image, and quit the
+ loop if it isn't.
+
+We have not changed loops which might, in principle, iterate over the
+whole image - even if they might do so one byte at a time with a
+nontrivial access check function in the middle.
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+
+v3: Fix a whitespace error.
+
+v2: BUGFIX: elf_shdr_by_name, elf_note_next: Reject new <= old, not just <.
+ elf_shdr_by_name: Change order of checks to be a bit clearer.
+ elf_load_bsdsyms: shdr loop check, improve chance of brokenness detection.
+ Style fixes.
+---
+ tools/libxc/xc_dom_elfloader.c | 3 +++
+ xen/common/libelf/libelf-dominfo.c | 14 ++++++++++++++
+ xen/common/libelf/libelf-loader.c | 27 +++++++++++++++++++++++++--
+ xen/common/libelf/libelf-tools.c | 11 ++++++++++-
+ 4 files changed, 52 insertions(+), 3 deletions(-)
+
+diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
+index d9b1a43..9bd3708 100644
+--- a/tools/libxc/xc_dom_elfloader.c
++++ b/tools/libxc/xc_dom_elfloader.c
+@@ -224,6 +224,9 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+ for ( h = 0; h < count; h++ )
+ {
+ shdr = ELF_OBSOLETE_VOIDP_CAST elf_shdr_by_index(&syms, h);
++ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
++ /* input has an insane section header count field */
++ break;
+ type = elf_uval(&syms, shdr, sh_type);
+ if ( type == SHT_STRTAB )
+ {
+diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
+index e837d4d..8189fa5 100644
+--- a/xen/common/libelf/libelf-dominfo.c
++++ b/xen/common/libelf/libelf-dominfo.c
+@@ -485,6 +485,13 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
+ for ( i = 0; i < count; i++ )
+ {
+ phdr = elf_phdr_by_index(elf, i);
++ /*
++ * This test also arranges for the loop to terminate if the
++ * input file has a ridiculous value for the header count: The
++ * first putative header outside the input image will appear
++ * to have type 0 (since out-of-range accesses read as 0) and
++ * PT_NOTE != 0.
++ */
+ if ( elf_uval(elf, phdr, p_type) != PT_NOTE )
+ continue;
+
+@@ -515,6 +522,10 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
+ {
+ shdr = elf_shdr_by_index(elf, i);
+
++ /*
++ * See above re guarantee of loop termination.
++ * SHT_NOTE != 0.
++ */
+ if ( elf_uval(elf, shdr, sh_type) != SHT_NOTE )
+ continue;
+
+@@ -552,6 +563,9 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
+ elf_xen_parse_guest_info(elf, parms);
+ break;
+ }
++ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
++ /* input has an insane section header count field */
++ break;
+ }
+ }
+
+diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
+index c3a9e51..a6c97d0 100644
+--- a/xen/common/libelf/libelf-loader.c
++++ b/xen/common/libelf/libelf-loader.c
+@@ -75,6 +75,9 @@ elf_errorstatus elf_init(struct elf_binary *elf, const char *image_input, size_t
+ for ( i = 0; i < count; i++ )
+ {
+ shdr = elf_shdr_by_index(elf, i);
++ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
++ /* input has an insane section header count field */
++ break;
+ if ( elf_uval(elf, shdr, sh_type) != SHT_SYMTAB )
+ continue;
+ elf->sym_tab = shdr;
+@@ -170,6 +173,9 @@ void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart)
+ for ( i = 0; i < elf_shdr_count(elf); i++ )
+ {
+ shdr = elf_shdr_by_index(elf, i);
++ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
++ /* input has an insane section header count field */
++ break;
+ type = elf_uval(elf, shdr, sh_type);
+ if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) )
+ sz = elf_round_up(elf, sz + elf_uval(elf, shdr, sh_size));
+@@ -224,6 +230,9 @@ do { \
+
+ for ( i = 0; i < elf_shdr_count(elf); i++ )
+ {
++ elf_ptrval old_shdr_p;
++ elf_ptrval new_shdr_p;
++
+ type = elf_uval(elf, shdr, sh_type);
+ if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) )
+ {
+@@ -235,8 +244,16 @@ do { \
+ elf_hdr_elm(elf, shdr, sh_offset, maxva - symtab_addr);
+ maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (unsigned long)maxva + sz);
+ }
+- shdr = ELF_MAKE_HANDLE(elf_shdr, ELF_HANDLE_PTRVAL(shdr) +
+- (unsigned long)elf_uval(elf, elf->ehdr, e_shentsize));
++ old_shdr_p = ELF_HANDLE_PTRVAL(shdr);
++ new_shdr_p = old_shdr_p + elf_uval(elf, elf->ehdr, e_shentsize);
++ if ( new_shdr_p <= old_shdr_p ) /* wrapped or stuck */
++ {
++ elf_mark_broken(elf, "bad section header length");
++ break;
++ }
++ if ( !elf_access_ok(elf, new_shdr_p, 1) ) /* outside image */
++ break;
++ shdr = ELF_MAKE_HANDLE(elf_shdr, new_shdr_p);
+ }
+
+ /* Write down the actual sym size. */
+@@ -256,6 +273,9 @@ void elf_parse_binary(struct elf_binary *elf)
+ for ( i = 0; i < count; i++ )
+ {
+ phdr = elf_phdr_by_index(elf, i);
++ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(phdr), 1) )
++ /* input has an insane program header count field */
++ break;
+ if ( !elf_phdr_is_loadable(elf, phdr) )
+ continue;
+ paddr = elf_uval(elf, phdr, p_paddr);
+@@ -283,6 +303,9 @@ elf_errorstatus elf_load_binary(struct elf_binary *elf)
+ for ( i = 0; i < count; i++ )
+ {
+ phdr = elf_phdr_by_index(elf, i);
++ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(phdr), 1) )
++ /* input has an insane program header count field */
++ break;
+ if ( !elf_phdr_is_loadable(elf, phdr) )
+ continue;
+ paddr = elf_uval(elf, phdr, p_paddr);
+diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
+index 308ea15..eb89c31 100644
+--- a/xen/common/libelf/libelf-tools.c
++++ b/xen/common/libelf/libelf-tools.c
+@@ -145,6 +145,9 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
+
+ for ( i = 0; i < count; i++ )
+ {
++ if (!elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1))
++ /* input has an insane section header count field */
++ break;
+ shdr = elf_shdr_by_index(elf, i);
+ sname = elf_section_name(elf, shdr);
+ if ( sname && !strcmp(sname, name) )
+@@ -324,7 +327,13 @@ ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(
+ unsigned namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
+ unsigned descsz = (elf_uval(elf, note, descsz) + 3) & ~3;
+
+- return ELF_MAKE_HANDLE(elf_note, ELF_HANDLE_PTRVAL(note) + elf_size(elf, note) + namesz + descsz);
++ elf_ptrval ptrval = ELF_HANDLE_PTRVAL(note)
++ + elf_size(elf, note) + namesz + descsz;
++
++ if (ptrval <= ELF_HANDLE_PTRVAL(note))
++ ptrval = ELF_MAX_PTRVAL; /* terminate caller's loop */
++
++ return ELF_MAKE_HANDLE(elf_note, ptrval);
+ }
+
+ /* ------------------------------------------------------------------------ */
+--
+1.7.2.5
+
diff --git a/xsa55-4.20016-libelf-abolish-obsolete-macros.patch b/xsa55-4.20016-libelf-abolish-obsolete-macros.patch
new file mode 100644
index 0000000..dd7b9c9
--- /dev/null
+++ b/xsa55-4.20016-libelf-abolish-obsolete-macros.patch
@@ -0,0 +1,406 @@
+From fc5f528dd442e9c65dccd0c6f4bd8904f4ececac Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 24 May 2013 17:52:43 +0100
+Subject: [PATCH 16/16] libelf: abolish obsolete macros
+
+Abolish ELF_PTRVAL_[CONST_]{CHAR,VOID}; change uses to elf_ptrval.
+Abolish ELF_HANDLE_DECL_NONCONST; change uses to ELF_HANDLE_DECL.
+Abolish ELF_OBSOLETE_VOIDP_CAST; simply remove all uses.
+
+No functional change. (Verified by diffing assembler output.)
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+Acked-by: Ian Campbell <ian.campbell at citrix.com>
+
+v2: New patch.
+---
+ tools/libxc/xc_dom_elfloader.c | 8 +++---
+ tools/xcutils/readnotes.c | 2 +-
+ xen/common/libelf/libelf-dominfo.c | 6 ++--
+ xen/common/libelf/libelf-loader.c | 24 +++++++++---------
+ xen/common/libelf/libelf-tools.c | 24 +++++++++---------
+ xen/include/xen/libelf.h | 48 +++++++++---------------------------
+ 6 files changed, 44 insertions(+), 68 deletions(-)
+
+diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
+index 9bd3708..004ff51 100644
+--- a/tools/libxc/xc_dom_elfloader.c
++++ b/tools/libxc/xc_dom_elfloader.c
+@@ -115,9 +115,9 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+ struct elf_binary *elf, bool load)
+ {
+ struct elf_binary syms;
+- ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr; ELF_HANDLE_DECL(elf_shdr) shdr2;
++ ELF_HANDLE_DECL(elf_shdr) shdr; ELF_HANDLE_DECL(elf_shdr) shdr2;
+ xen_vaddr_t symtab, maxaddr;
+- ELF_PTRVAL_CHAR hdr;
++ elf_ptrval hdr;
+ size_t size;
+ unsigned h, count, type, i, tables = 0;
+ unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
+@@ -223,7 +223,7 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+ count = elf_shdr_count(&syms);
+ for ( h = 0; h < count; h++ )
+ {
+- shdr = ELF_OBSOLETE_VOIDP_CAST elf_shdr_by_index(&syms, h);
++ shdr = elf_shdr_by_index(&syms, h);
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
+ /* input has an insane section header count field */
+ break;
+@@ -267,7 +267,7 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+ if ( load )
+ {
+ shdr2 = elf_shdr_by_index(elf, h);
+- elf_memcpy_safe(elf, ELF_OBSOLETE_VOIDP_CAST elf_section_start(&syms, shdr),
++ elf_memcpy_safe(elf, elf_section_start(&syms, shdr),
+ elf_section_start(elf, shdr2),
+ size);
+ }
+diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
+index 9be1594..4ff7085 100644
+--- a/tools/xcutils/readnotes.c
++++ b/tools/xcutils/readnotes.c
+@@ -80,7 +80,7 @@ static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf,
+ ELF_HANDLE_DECL(elf_note) note)
+ {
+ unsigned descsz = elf_uval(elf, note, descsz);
+- ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
++ elf_ptrval desc = elf_note_desc(elf, note);
+
+ /* XXX should be able to cope with a list of values. */
+ switch ( descsz / 2 )
+diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
+index 8189fa5..21e82c9 100644
+--- a/xen/common/libelf/libelf-dominfo.c
++++ b/xen/common/libelf/libelf-dominfo.c
+@@ -218,8 +218,8 @@ elf_errorstatus elf_xen_parse_note(struct elf_binary *elf,
+
+ static unsigned elf_xen_parse_notes(struct elf_binary *elf,
+ struct elf_dom_parms *parms,
+- ELF_PTRVAL_CONST_VOID start,
+- ELF_PTRVAL_CONST_VOID end)
++ elf_ptrval start,
++ elf_ptrval end)
+ {
+ unsigned xen_elfnotes = 0;
+ ELF_HANDLE_DECL(elf_note) note;
+@@ -249,7 +249,7 @@ static unsigned elf_xen_parse_notes(struct elf_binary *elf,
+ elf_errorstatus elf_xen_parse_guest_info(struct elf_binary *elf,
+ struct elf_dom_parms *parms)
+ {
+- ELF_PTRVAL_CONST_CHAR h;
++ elf_ptrval h;
+ unsigned char name[32], value[128];
+ unsigned len;
+
+diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
+index a6c97d0..6cf9622 100644
+--- a/xen/common/libelf/libelf-loader.c
++++ b/xen/common/libelf/libelf-loader.c
+@@ -118,7 +118,7 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
+ }
+
+ static elf_errorstatus elf_load_image(struct elf_binary *elf,
+- ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src,
++ elf_ptrval dst, elf_ptrval src,
+ uint64_t filesz, uint64_t memsz)
+ {
+ elf_memcpy_safe(elf, dst, src, filesz);
+@@ -132,7 +132,7 @@ void elf_set_verbose(struct elf_binary *elf)
+ elf->verbose = 1;
+ }
+
+-static elf_errorstatus elf_load_image(struct elf_binary *elf, ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src, uint64_t filesz, uint64_t memsz)
++static elf_errorstatus elf_load_image(struct elf_binary *elf, elf_ptrval dst, elf_ptrval src, uint64_t filesz, uint64_t memsz)
+ {
+ elf_errorstatus rc;
+ if ( filesz > ULONG_MAX || memsz > ULONG_MAX )
+@@ -187,12 +187,12 @@ void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart)
+
+ static void elf_load_bsdsyms(struct elf_binary *elf)
+ {
+- ELF_HANDLE_DECL_NONCONST(elf_ehdr) sym_ehdr;
++ ELF_HANDLE_DECL(elf_ehdr) sym_ehdr;
+ unsigned long sz;
+- ELF_PTRVAL_VOID maxva;
+- ELF_PTRVAL_VOID symbase;
+- ELF_PTRVAL_VOID symtab_addr;
+- ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr;
++ elf_ptrval maxva;
++ elf_ptrval symbase;
++ elf_ptrval symtab_addr;
++ ELF_HANDLE_DECL(elf_shdr) shdr;
+ unsigned i, type;
+
+ if ( !elf->bsd_symtab_pstart )
+@@ -226,7 +226,7 @@ do { \
+ elf_memcpy_safe(elf, ELF_HANDLE_PTRVAL(shdr),
+ ELF_IMAGE_BASE(elf) + elf_uval(elf, elf->ehdr, e_shoff),
+ sz);
+- maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (unsigned long)maxva + sz);
++ maxva = elf_round_up(elf, (unsigned long)maxva + sz);
+
+ for ( i = 0; i < elf_shdr_count(elf); i++ )
+ {
+@@ -242,7 +242,7 @@ do { \
+ elf_memcpy_safe(elf, maxva, elf_section_start(elf, shdr), sz);
+ /* Mangled to be based on ELF header location. */
+ elf_hdr_elm(elf, shdr, sh_offset, maxva - symtab_addr);
+- maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (unsigned long)maxva + sz);
++ maxva = elf_round_up(elf, (unsigned long)maxva + sz);
+ }
+ old_shdr_p = ELF_HANDLE_PTRVAL(shdr);
+ new_shdr_p = old_shdr_p + elf_uval(elf, elf->ehdr, e_shentsize);
+@@ -297,7 +297,7 @@ elf_errorstatus elf_load_binary(struct elf_binary *elf)
+ {
+ ELF_HANDLE_DECL(elf_phdr) phdr;
+ uint64_t i, count, paddr, offset, filesz, memsz;
+- ELF_PTRVAL_VOID dest;
++ elf_ptrval dest;
+
+ count = elf_uval(elf, elf->ehdr, e_phnum);
+ for ( i = 0; i < count; i++ )
+@@ -314,7 +314,7 @@ elf_errorstatus elf_load_binary(struct elf_binary *elf)
+ memsz = elf_uval(elf, phdr, p_memsz);
+ dest = elf_get_ptr(elf, paddr);
+ elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%"ELF_PRPTRVAL" -> 0x%"ELF_PRPTRVAL"\n",
+- __func__, i, dest, (ELF_PTRVAL_VOID)(dest + filesz));
++ __func__, i, dest, (elf_ptrval)(dest + filesz));
+ if ( elf_load_image(elf, dest, ELF_IMAGE_BASE(elf) + offset, filesz, memsz) != 0 )
+ return -1;
+ }
+@@ -323,7 +323,7 @@ elf_errorstatus elf_load_binary(struct elf_binary *elf)
+ return 0;
+ }
+
+-ELF_PTRVAL_VOID elf_get_ptr(struct elf_binary *elf, unsigned long addr)
++elf_ptrval elf_get_ptr(struct elf_binary *elf, unsigned long addr)
+ {
+ return ELF_REALPTR2PTRVAL(elf->dest_base) + addr - elf->pstart;
+ }
+diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
+index eb89c31..27c9841 100644
+--- a/xen/common/libelf/libelf-tools.c
++++ b/xen/common/libelf/libelf-tools.c
+@@ -159,7 +159,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
+ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, unsigned index)
+ {
+ uint64_t count = elf_shdr_count(elf);
+- ELF_PTRVAL_CONST_VOID ptr;
++ elf_ptrval ptr;
+
+ if ( index >= count )
+ return ELF_INVALID_HANDLE(elf_shdr);
+@@ -173,7 +173,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, unsigned ind
+ ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, unsigned index)
+ {
+ uint64_t count = elf_uval(elf, elf->ehdr, e_phnum);
+- ELF_PTRVAL_CONST_VOID ptr;
++ elf_ptrval ptr;
+
+ if ( index >= count )
+ return ELF_INVALID_HANDLE(elf_phdr);
+@@ -216,24 +216,24 @@ const char *elf_strfmt(struct elf_binary *elf, elf_ptrval start)
+ return str;
+ }
+
+-ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
++elf_ptrval elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
+ {
+ return ELF_IMAGE_BASE(elf) + elf_uval(elf, shdr, sh_offset);
+ }
+
+-ELF_PTRVAL_CONST_VOID elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
++elf_ptrval elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
+ {
+ return ELF_IMAGE_BASE(elf)
+ + elf_uval(elf, shdr, sh_offset) + elf_uval(elf, shdr, sh_size);
+ }
+
+-ELF_PTRVAL_CONST_VOID elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
++elf_ptrval elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
+ {
+ return ELF_IMAGE_BASE(elf)
+ + elf_uval(elf, phdr, p_offset);
+ }
+
+-ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
++elf_ptrval elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
+ {
+ return ELF_IMAGE_BASE(elf)
+ + elf_uval(elf, phdr, p_offset) + elf_uval(elf, phdr, p_filesz);
+@@ -241,8 +241,8 @@ ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(el
+
+ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol)
+ {
+- ELF_PTRVAL_CONST_VOID ptr = elf_section_start(elf, elf->sym_tab);
+- ELF_PTRVAL_CONST_VOID end = elf_section_end(elf, elf->sym_tab);
++ elf_ptrval ptr = elf_section_start(elf, elf->sym_tab);
++ elf_ptrval end = elf_section_end(elf, elf->sym_tab);
+ ELF_HANDLE_DECL(elf_sym) sym;
+ uint64_t info, name;
+ const char *sym_name;
+@@ -266,7 +266,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym
+
+ ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, unsigned index)
+ {
+- ELF_PTRVAL_CONST_VOID ptr = elf_section_start(elf, elf->sym_tab);
++ elf_ptrval ptr = elf_section_start(elf, elf->sym_tab);
+ ELF_HANDLE_DECL(elf_sym) sym;
+
+ sym = ELF_MAKE_HANDLE(elf_sym, ptr + index * elf_size(elf, sym));
+@@ -278,7 +278,7 @@ const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note
+ return elf_strval(elf, ELF_HANDLE_PTRVAL(note) + elf_size(elf, note));
+ }
+
+-ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
++elf_ptrval elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
+ {
+ unsigned namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
+
+@@ -287,7 +287,7 @@ ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_
+
+ uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
+ {
+- ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
++ elf_ptrval desc = elf_note_desc(elf, note);
+ unsigned descsz = elf_uval(elf, note, descsz);
+
+ switch (descsz)
+@@ -305,7 +305,7 @@ uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note
+ uint64_t elf_note_numeric_array(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note,
+ unsigned int unitsz, unsigned int idx)
+ {
+- ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
++ elf_ptrval desc = elf_note_desc(elf, note);
+ unsigned descsz = elf_uval(elf, note, descsz);
+
+ if ( descsz % unitsz || idx >= descsz / unitsz )
+diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
+index 4fc2496..b78d8a7 100644
+--- a/xen/include/xen/libelf.h
++++ b/xen/include/xen/libelf.h
+@@ -58,13 +58,8 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
+ /*
+ * We abstract away the pointerness of these pointers, replacing
+ * various void*, char* and struct* with the following:
+- * PTRVAL A pointer to a byte; one can do pointer arithmetic
++ * elf_ptrval A pointer to a byte; one can do pointer arithmetic
+ * on this.
+- * This replaces variables which were char*,void*
+- * and their const versions, so we provide four
+- * different obsolete declaration macros:
+- * ELF_PTRVAL_{,CONST}{VOID,CHAR}
+- * New code can simply use the elf_ptrval typedef.
+ * HANDLE A pointer to a struct. There is one of these types
+ * for each pointer type - that is, for each "structname".
+ * In the arguments to the various HANDLE macros, structname
+@@ -73,8 +68,6 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
+ * pointers. In the current code attempts to do so will
+ * compile, but in the next patch this will become a
+ * compile error.
+- * We also provide a second declaration macro for
+- * pointers which were to const; this is obsolete.
+ */
+
+ typedef uintptr_t elf_ptrval;
+@@ -82,15 +75,9 @@ typedef uintptr_t elf_ptrval;
+ #define ELF_REALPTR2PTRVAL(realpointer) ((elf_ptrval)(realpointer))
+ /* Converts an actual C pointer into a PTRVAL */
+
+-#define ELF_HANDLE_DECL_NONCONST(structname) structname##_handle /*obsolete*/
+ #define ELF_HANDLE_DECL(structname) structname##_handle
+ /* Provides a type declaration for a HANDLE. */
+
+-#define ELF_PTRVAL_VOID elf_ptrval /*obsolete*/
+-#define ELF_PTRVAL_CHAR elf_ptrval /*obsolete*/
+-#define ELF_PTRVAL_CONST_VOID elf_ptrval /*obsolete*/
+-#define ELF_PTRVAL_CONST_CHAR elf_ptrval /*obsolete*/
+-
+ /* printf format a la PRId... for a PTRVAL */
+ #ifdef __XEN__
+ #define ELF_PRPTRVAL "lu"
+@@ -121,17 +108,6 @@ typedef uintptr_t elf_ptrval;
+ #define ELF_HANDLE_PTRVAL(handleval) ((handleval).ptrval)
+ /* Converts a HANDLE to a PTRVAL. */
+
+-#define ELF_OBSOLETE_VOIDP_CAST /*empty*/
+- /*
+- * In some places the old code used to need to
+- * - cast away const (the existing code uses const a fair
+- * bit but actually sometimes wants to write to its input)
+- * from a PTRVAL.
+- * - convert an integer representing a pointer to a PTRVAL
+- * Nowadays all of these re uintptr_ts so there is no const problem
+- * and no need for any casting.
+- */
+-
+ #define ELF_UNSAFE_PTR(ptrval) ((void*)(uintptr_t)(ptrval))
+ /*
+ * Turns a PTRVAL into an actual C pointer. Before this is done
+@@ -208,7 +184,7 @@ struct elf_binary {
+ char data;
+
+ ELF_HANDLE_DECL(elf_ehdr) ehdr;
+- ELF_PTRVAL_CONST_CHAR sec_strtab;
++ elf_ptrval sec_strtab;
+ ELF_HANDLE_DECL(elf_shdr) sym_tab;
+ uint64_t sym_strtab;
+
+@@ -286,7 +262,7 @@ struct elf_binary {
+ * str should be a HANDLE.
+ */
+
+-uint64_t elf_access_unsigned(struct elf_binary *elf, ELF_PTRVAL_CONST_VOID ptr,
++uint64_t elf_access_unsigned(struct elf_binary *elf, elf_ptrval ptr,
+ uint64_t offset, size_t size);
+ /* Reads a field at arbitrary offset and alignemnt */
+
+@@ -338,17 +314,17 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, unsigned ind
+ ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, unsigned index);
+
+ const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr); /* might return NULL if inputs are invalid */
+-ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
+-ELF_PTRVAL_CONST_VOID elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
++elf_ptrval elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
++elf_ptrval elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
+
+-ELF_PTRVAL_CONST_VOID elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
+-ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
++elf_ptrval elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
++elf_ptrval elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
+
+ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol);
+ ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, unsigned index);
+
+ const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); /* may return NULL */
+-ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
++elf_ptrval elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
+ uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
+ uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
+ unsigned int unitsz, unsigned int idx);
+@@ -375,7 +351,7 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback*,
+ void elf_parse_binary(struct elf_binary *elf);
+ elf_errorstatus elf_load_binary(struct elf_binary *elf);
+
+-ELF_PTRVAL_VOID elf_get_ptr(struct elf_binary *elf, unsigned long addr);
++elf_ptrval elf_get_ptr(struct elf_binary *elf, unsigned long addr);
+ uint64_t elf_lookup_addr(struct elf_binary *elf, const char *symbol);
+
+ void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart); /* private */
+@@ -410,9 +386,9 @@ struct xen_elfnote {
+
+ struct elf_dom_parms {
+ /* raw */
+- ELF_PTRVAL_CONST_CHAR guest_info;
+- ELF_PTRVAL_CONST_VOID elf_note_start;
+- ELF_PTRVAL_CONST_VOID elf_note_end;
++ elf_ptrval guest_info;
++ elf_ptrval elf_note_start;
++ elf_ptrval elf_note_end;
+ struct xen_elfnote elf_notes[XEN_ELFNOTE_MAX + 1];
+
+ /* parsed */
+--
+1.7.2.5
+
More information about the scm-commits
mailing list