[xen] Revised fixes for [XSA-55]

myoung myoung at fedoraproject.org
Fri Jun 14 18:15:18 UTC 2013


commit 454702a517ea330976d687398461432c99d149f7
Author: Michael Young <m.a.young at durham.ac.uk>
Date:   Fri Jun 14 19:13:05 2013 +0100

    Revised fixes for [XSA-55]

 xen.spec                                           |   47 ++-
 ...-4.20001-libelf-abolish-libelf-relocate.c.patch |    8 +-
 ...2-libxc-introduce-xc_dom_seg_to_ptr_pages.patch |   40 ++-
 ...x-range-checking-in-xc_dom_pfn_to_ptr-etc.patch |  156 ++++++++
 ...struct-elf_binary-parameter-to-elf_load_i.patch |    8 +-
 ...lf-abolish-elf_sval-and-elf_access_signed.patch |    8 +-
 ...-include-of-asm-guest_access.h-to-top-of-.patch |    8 +-
 ...om_load_elf_symtab-Do-not-use-syms-uninit.patch |   14 +-
 ...oduce-macros-for-memory-access-and-pointe.patch |   56 +--
 ...ls-readnotes-adjust-print_l1_mfn_valid_no.patch |   10 +-
 ...elf-check-nul-terminated-strings-properly.patch |   27 +-
 ...4.20011-libelf-check-all-pointer-accesses.patch |  134 +++----
 ...ck-pointer-references-in-elf_is_elfbinary.patch |   32 +-
 ...lf-Make-all-callers-call-elf_check_broken.patch |   37 +-
 ...-4.20014-libelf-use-C99-bool-for-booleans.patch |   41 +-
 ...20015-libelf-check-loops-for-running-away.patch |  195 ----------
 ...4.20015-libelf-use-only-unsigned-integers.patch |  118 +++---
 ...20016-libelf-check-loops-for-running-away.patch |  409 ++++++++++++++++++++
 ...55-4.20017-libelf-abolish-obsolete-macros.patch |   90 +++---
 ...xc-Add-range-checking-to-xc_dom_binloader.patch |   69 ++++
 ...-failure-of-xc_dom_-_to_ptr-xc_map_foreig.patch |  382 ++++++++++++++++++
 ...020-libxc-check-return-values-from-malloc.patch |  272 +++++++++++++
 ...ange-checks-in-xc_dom_p2m_host-and-_guest.patch |   47 +++
 ...-blob-size-before-proceeding-in-xc_dom_ch.patch |   31 ++
 ...etter-range-check-in-xc_dom_alloc_segment.patch |   33 ++
 25 files changed, 1733 insertions(+), 539 deletions(-)
---
diff --git a/xen.spec b/xen.spec
index 976a374..da50702 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: 6%{?dist}
+Release: 7%{?dist}
 Group:   Development/Libraries
 License: GPLv2+ and LGPLv2+ and BSD
 URL:     http://xen.org/
@@ -93,20 +93,27 @@ 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
+Patch80: xsa55-4.20003-libxc-Fix-range-checking-in-xc_dom_pfn_to_ptr-etc.patch
+Patch81: xsa55-4.20004-libelf-add-struct-elf_binary-parameter-to-elf_load_i.patch
+Patch82: xsa55-4.20005-libelf-abolish-elf_sval-and-elf_access_signed.patch
+Patch83: xsa55-4.20006-libelf-move-include-of-asm-guest_access.h-to-top-of-.patch
+Patch84: xsa55-4.20007-libelf-xc_dom_load_elf_symtab-Do-not-use-syms-uninit.patch
+Patch85: xsa55-4.20008-libelf-introduce-macros-for-memory-access-and-pointe.patch
+Patch86: xsa55-4.20009-tools-xcutils-readnotes-adjust-print_l1_mfn_valid_no.patch
+Patch87: xsa55-4.20010-libelf-check-nul-terminated-strings-properly.patch
+Patch88: xsa55-4.20011-libelf-check-all-pointer-accesses.patch
+Patch89: xsa55-4.20012-libelf-Check-pointer-references-in-elf_is_elfbinary.patch
+Patch90: xsa55-4.20013-libelf-Make-all-callers-call-elf_check_broken.patch
+Patch91: xsa55-4.20014-libelf-use-C99-bool-for-booleans.patch
+Patch92: xsa55-4.20015-libelf-use-only-unsigned-integers.patch
+Patch93: xsa55-4.20016-libelf-check-loops-for-running-away.patch
+Patch94: xsa55-4.20017-libelf-abolish-obsolete-macros.patch
+Patch95: xsa55-4.20018-libxc-Add-range-checking-to-xc_dom_binloader.patch
+Patch96: xsa55-4.20019-libxc-check-failure-of-xc_dom_-_to_ptr-xc_map_foreig.patch
+Patch97: xsa55-4.20020-libxc-check-return-values-from-malloc.patch
+Patch98: xsa55-4.20021-libxc-range-checks-in-xc_dom_p2m_host-and-_guest.patch
+Patch99: xsa55-4.20022-libxc-check-blob-size-before-proceeding-in-xc_dom_ch.patch
+Patch101: xsa55-4.20023-libxc-Better-range-check-in-xc_dom_alloc_segment.patch
 
 Patch100: xen-configure-xend.patch
 
@@ -305,6 +312,13 @@ manage Xen virtual machines.
 %patch91 -p1
 %patch92 -p1
 %patch93 -p1
+%patch94 -p1
+%patch95 -p1
+%patch96 -p1
+%patch97 -p1
+%patch98 -p1
+%patch99 -p1
+%patch101 -p1
 
 %patch100 -p1
 
@@ -794,6 +808,9 @@ rm -rf %{buildroot}
 %endif
 
 %changelog
+* Fri Jun 14 2013 Michael Young <m.a.young at durham.ac.uk> - 4.2.2-7
+- Revised fixes for [XSA-55] (#970640)
+
 * 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)
diff --git a/xsa55-4.20001-libelf-abolish-libelf-relocate.c.patch b/xsa55-4.20001-libelf-abolish-libelf-relocate.c.patch
index 83070aa..315735d 100644
--- a/xsa55-4.20001-libelf-abolish-libelf-relocate.c.patch
+++ b/xsa55-4.20001-libelf-abolish-libelf-relocate.c.patch
@@ -1,7 +1,7 @@
-From d9d5d3ad927503fe89eece9b8e19eaab3e335e94 Mon Sep 17 00:00:00 2001
+From 9737484becab4a25159f1e985700eaee89690d34 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
+Date: Fri, 14 Jun 2013 16:43:15 +0100
+Subject: [PATCH 01/23] libelf: abolish libelf-relocate.c
 
 This file is not actually used.  It's not built in Xen's instance of
 libelf; in libxc's it's built but nothing in it is called.  Do not
@@ -11,6 +11,8 @@ This reduces the amount of work we need to do in forthcoming patches
 to libelf (particularly since as libelf-relocate.c is not used it is
 probably full of bugs).
 
+This is part of the fix to a security issue, XSA-55.
+
 Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
 Acked-by: Ian Campbell <ian.campbell at citrix.com>
 ---
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
index b4ed541..c26605f 100644
--- 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
@@ -1,24 +1,26 @@
-From 8d895cda49f5334fc8248d2c802dc890cfbb03f0 Mon Sep 17 00:00:00 2001
+From a672da4b2d58ef12be9d7407160e9fb43cac75d9 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
+Date: Fri, 14 Jun 2013 16:43:16 +0100
+Subject: [PATCH 02/23] 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.
 
+This is part of the fix to a security issue, XSA-55.
+
 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(-)
+ tools/libxc/xc_dom.h |   19 ++++++++++++++++---
+ 1 files changed, 16 insertions(+), 3 deletions(-)
 
 diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h
-index 6a72aa9..b74252f 100644
+index 6a72aa9..9af2195 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,
+@@ -278,14 +278,27 @@ 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);
  
@@ -31,20 +33,24 @@ index 6a72aa9..b74252f 100644
      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);
- }
- 
++    void *retval;
++
++    retval = xc_dom_pfn_to_ptr(dom, seg->pfn, pages);
++
++    *pages_out = retval ? pages : 0;
++    return retval;
++}
++
 +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);
-+}
-+
++    xen_pfn_t dummy;
+ 
+-    return xc_dom_pfn_to_ptr(dom, seg->pfn, pages);
++    return xc_dom_seg_to_ptr_pages(dom, seg, &dummy);
+ }
+ 
  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-libxc-Fix-range-checking-in-xc_dom_pfn_to_ptr-etc.patch b/xsa55-4.20003-libxc-Fix-range-checking-in-xc_dom_pfn_to_ptr-etc.patch
new file mode 100644
index 0000000..5930321
--- /dev/null
+++ b/xsa55-4.20003-libxc-Fix-range-checking-in-xc_dom_pfn_to_ptr-etc.patch
@@ -0,0 +1,156 @@
+From 8c738fa5c1f3cfcd935b6191b3526f7ac8b2a5bd Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 14 Jun 2013 16:43:16 +0100
+Subject: [PATCH 03/23] libxc: Fix range checking in xc_dom_pfn_to_ptr etc.
+
+* Ensure that xc_dom_pfn_to_ptr (when called with count==0) does not
+  return a previously-allocated block which is entirely before the
+  requested pfn (!)
+
+* Provide a version of xc_dom_pfn_to_ptr, xc_dom_pfn_to_ptr_retcount,
+  which provides the length of the mapped region via an out parameter.
+
+* Change xc_dom_vaddr_to_ptr to always provide the length of the
+  mapped region and change the call site in xc_dom_binloader.c to
+  check it.  The call site in xc_dom_load_elf_symtab will be corrected
+  in a forthcoming patch, and for now ignores the returned length.
+
+This is part of the fix to a security issue, XSA-55.
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+---
+ tools/libxc/xc_dom.h           |   16 +++++++++++++---
+ tools/libxc/xc_dom_binloader.c |   11 ++++++++++-
+ tools/libxc/xc_dom_core.c      |   13 +++++++++++++
+ tools/libxc/xc_dom_elfloader.c |    3 ++-
+ 4 files changed, 38 insertions(+), 5 deletions(-)
+
+diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h
+index 9af2195..9f8037e 100644
+--- a/tools/libxc/xc_dom.h
++++ b/tools/libxc/xc_dom.h
+@@ -275,6 +275,8 @@ int xc_dom_alloc_segment(struct xc_dom_image *dom,
+ 
+ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t first,
+                         xen_pfn_t count);
++void *xc_dom_pfn_to_ptr_retcount(struct xc_dom_image *dom, xen_pfn_t first,
++                                 xen_pfn_t count, xen_pfn_t *count_out);
+ void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn);
+ void xc_dom_unmap_all(struct xc_dom_image *dom);
+ 
+@@ -302,13 +304,21 @@ static inline void *xc_dom_seg_to_ptr(struct xc_dom_image *dom,
+ }
+ 
+ static inline void *xc_dom_vaddr_to_ptr(struct xc_dom_image *dom,
+-                                        xen_vaddr_t vaddr)
++                                        xen_vaddr_t vaddr,
++                                        size_t *safe_region_out)
+ {
+     unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
+     xen_pfn_t page = (vaddr - dom->parms.virt_base) / page_size;
+     unsigned int offset = (vaddr - dom->parms.virt_base) % page_size;
+-    void *ptr = xc_dom_pfn_to_ptr(dom, page, 0);
+-    return (ptr ? (ptr + offset) : NULL);
++    xen_pfn_t safe_region_count;
++    void *ptr;
++
++    *safe_region_out = 0;
++    ptr = xc_dom_pfn_to_ptr_retcount(dom, page, 0, &safe_region_count);
++    if ( ptr == NULL )
++        return ptr;
++    *safe_region_out = (safe_region_count << XC_DOM_PAGE_SHIFT(dom)) - offset;
++    return ptr;
+ }
+ 
+ static inline int xc_dom_feature_translated(struct xc_dom_image *dom)
+diff --git a/tools/libxc/xc_dom_binloader.c b/tools/libxc/xc_dom_binloader.c
+index 769e97d..bde93f7 100644
+--- a/tools/libxc/xc_dom_binloader.c
++++ b/tools/libxc/xc_dom_binloader.c
+@@ -249,6 +249,7 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
+     char *image = dom->kernel_blob;
+     char *dest;
+     size_t image_size = dom->kernel_size;
++    size_t dest_size;
+     uint32_t start_addr;
+     uint32_t load_end_addr;
+     uint32_t bss_end_addr;
+@@ -272,7 +273,15 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
+     DOMPRINTF("  text_size: 0x%" PRIx32 "", text_size);
+     DOMPRINTF("  bss_size:  0x%" PRIx32 "", bss_size);
+ 
+-    dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart);
++    dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart, &dest_size);
++
++    if ( dest_size < text_size ||
++         dest_size - text_size < bss_size )
++    {
++        DOMPRINTF("%s: mapped region is too small for image", __FUNCTION__);
++        return -EINVAL;
++    }
++
+     memcpy(dest, image + skip, text_size);
+     memset(dest + text_size, 0, bss_size);
+ 
+diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
+index 2a01d7c..8913e41 100644
+--- a/tools/libxc/xc_dom_core.c
++++ b/tools/libxc/xc_dom_core.c
+@@ -351,10 +351,19 @@ int xc_dom_try_gunzip(struct xc_dom_image *dom, void **blob, size_t * size)
+ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
+                         xen_pfn_t count)
+ {
++    xen_pfn_t count_out_dummy;
++    return xc_dom_pfn_to_ptr_retcount(dom, pfn, count, &count_out_dummy);
++}
++
++void *xc_dom_pfn_to_ptr_retcount(struct xc_dom_image *dom, xen_pfn_t pfn,
++                                 xen_pfn_t count, xen_pfn_t *count_out)
++{
+     struct xc_dom_phys *phys;
+     unsigned int page_shift = XC_DOM_PAGE_SHIFT(dom);
+     char *mode = "unset";
+ 
++    *count_out = 0;
++
+     if ( pfn > dom->total_pages ||    /* multiple checks to avoid overflows */
+          count > dom->total_pages ||
+          pfn > dom->total_pages - count )
+@@ -384,6 +393,7 @@ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
+                           phys->count);
+                 return NULL;
+             }
++            *count_out = count;
+         }
+         else
+         {
+@@ -391,6 +401,9 @@ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
+                just hand out a pointer to it */
+             if ( pfn < phys->first )
+                 continue;
++            if ( pfn >= phys->first + phys->count )
++                continue;
++            *count_out = phys->count - (pfn - phys->first);
+         }
+         return phys->ptr + ((pfn - phys->first) << page_shift);
+     }
+diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
+index 2e69559..031b5b6 100644
+--- a/tools/libxc/xc_dom_elfloader.c
++++ b/tools/libxc/xc_dom_elfloader.c
+@@ -130,10 +130,11 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+ 
+     if ( load )
+     {
++        size_t allow_size; /* will be used in a forthcoming XSA-55 patch */
+         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);
++        hdr  = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start, &allow_size);
+         *(int *)hdr = size - sizeof(int);
+     }
+     else
+-- 
+1.7.2.5
+
diff --git a/xsa55-4.20003-libelf-add-struct-elf_binary-parameter-to-elf_load_i.patch b/xsa55-4.20004-libelf-add-struct-elf_binary-parameter-to-elf_load_i.patch
similarity index 89%
rename from xsa55-4.20003-libelf-add-struct-elf_binary-parameter-to-elf_load_i.patch
rename to xsa55-4.20004-libelf-add-struct-elf_binary-parameter-to-elf_load_i.patch
index 9d70887..6eb2bac 100644
--- a/xsa55-4.20003-libelf-add-struct-elf_binary-parameter-to-elf_load_i.patch
+++ b/xsa55-4.20004-libelf-add-struct-elf_binary-parameter-to-elf_load_i.patch
@@ -1,13 +1,15 @@
-From a9cd2c35b3575f18de2bd86f7d5c18d418b05f38 Mon Sep 17 00:00:00 2001
+From 035634047d10c678cbb8801c4263747bdaf4e5b1 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
+Date: Fri, 14 Jun 2013 16:43:16 +0100
+Subject: [PATCH 04/23] 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.
 
+This is part of the fix to a security issue, XSA-55.
+
 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>
diff --git a/xsa55-4.20004-libelf-abolish-elf_sval-and-elf_access_signed.patch b/xsa55-4.20005-libelf-abolish-elf_sval-and-elf_access_signed.patch
similarity index 92%
rename from xsa55-4.20004-libelf-abolish-elf_sval-and-elf_access_signed.patch
rename to xsa55-4.20005-libelf-abolish-elf_sval-and-elf_access_signed.patch
index 41c0a22..3f315c6 100644
--- a/xsa55-4.20004-libelf-abolish-elf_sval-and-elf_access_signed.patch
+++ b/xsa55-4.20005-libelf-abolish-elf_sval-and-elf_access_signed.patch
@@ -1,10 +1,12 @@
-From 917217105a652c06bd2139fd34f0e6f03f4795d0 Mon Sep 17 00:00:00 2001
+From 83ec905922b496e1a5756e3a88405eb6c2c6ba88 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
+Date: Fri, 14 Jun 2013 16:43:16 +0100
+Subject: [PATCH 05/23] libelf: abolish elf_sval and elf_access_signed
 
 These are not used anywhere.
 
+This is part of the fix to a security issue, XSA-55.
+
 Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
 Acked-by: Ian Campbell <ian.campbell at citrix.com>
 ---
diff --git a/xsa55-4.20005-libelf-move-include-of-asm-guest_access.h-to-top-of-.patch b/xsa55-4.20006-libelf-move-include-of-asm-guest_access.h-to-top-of-.patch
similarity index 86%
rename from xsa55-4.20005-libelf-move-include-of-asm-guest_access.h-to-top-of-.patch
rename to xsa55-4.20006-libelf-move-include-of-asm-guest_access.h-to-top-of-.patch
index 6bd383b..adbd32a 100644
--- a/xsa55-4.20005-libelf-move-include-of-asm-guest_access.h-to-top-of-.patch
+++ b/xsa55-4.20006-libelf-move-include-of-asm-guest_access.h-to-top-of-.patch
@@ -1,7 +1,7 @@
-From c2a7f97c7100532aac72de2e242ae97dde3737a0 Mon Sep 17 00:00:00 2001
+From 682a04488e7b3bd6c3448ab60599566eb7c6177a 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
+Date: Fri, 14 Jun 2013 16:43:16 +0100
+Subject: [PATCH 06/23] 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.
@@ -13,6 +13,8 @@ in headers #included from guest_access.h.
 
 No semantic or functional change in this patch.
 
+This is part of the fix to a security issue, XSA-55.
+
 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>
diff --git a/xsa55-4.20006-libelf-xc_dom_load_elf_symtab-Do-not-use-syms-uninit.patch b/xsa55-4.20007-libelf-xc_dom_load_elf_symtab-Do-not-use-syms-uninit.patch
similarity index 80%
rename from xsa55-4.20006-libelf-xc_dom_load_elf_symtab-Do-not-use-syms-uninit.patch
rename to xsa55-4.20007-libelf-xc_dom_load_elf_symtab-Do-not-use-syms-uninit.patch
index f5a655e..25425d0 100644
--- a/xsa55-4.20006-libelf-xc_dom_load_elf_symtab-Do-not-use-syms-uninit.patch
+++ b/xsa55-4.20007-libelf-xc_dom_load_elf_symtab-Do-not-use-syms-uninit.patch
@@ -1,7 +1,7 @@
-From 9ba416dd299ee3ad62dda7de3411210c78ee4ebc Mon Sep 17 00:00:00 2001
+From de9089b449d2508b1ba05590905c7ebaee00c8c4 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
+Date: Fri, 14 Jun 2013 16:43:16 +0100
+Subject: [PATCH 07/23] 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
@@ -15,19 +15,19 @@ 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.
 
+This is part of the fix to a security issue, XSA-55.
+
 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
+index 031b5b6..e82f6e9 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,
+@@ -144,7 +144,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
          hdr = xc_dom_malloc(dom, size);
          if ( hdr == NULL )
              return 0;
diff --git a/xsa55-4.20007-libelf-introduce-macros-for-memory-access-and-pointe.patch b/xsa55-4.20008-libelf-introduce-macros-for-memory-access-and-pointe.patch
similarity index 96%
rename from xsa55-4.20007-libelf-introduce-macros-for-memory-access-and-pointe.patch
rename to xsa55-4.20008-libelf-introduce-macros-for-memory-access-and-pointe.patch
index 335880f..a9256b5 100644
--- a/xsa55-4.20007-libelf-introduce-macros-for-memory-access-and-pointe.patch
+++ b/xsa55-4.20008-libelf-introduce-macros-for-memory-access-and-pointe.patch
@@ -1,7 +1,7 @@
-From 7ea097951208852fc01645a9fceec848212aa52c Mon Sep 17 00:00:00 2001
+From 40020ab55a1e9a1674ddecdb70299fab4fe8579d 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
+Date: Fri, 14 Jun 2013 16:43:17 +0100
+Subject: [PATCH 08/23] 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
@@ -15,12 +15,6 @@ 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"
@@ -53,6 +47,12 @@ Verification that this is all that's needed:
 
 I have not done this verification for ARM.
 
+This is part of the fix to a security issue, XSA-55.
+
+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>
+
 -8<- comparison-generate -8<-
  #!/bin/bash
  # usage:
@@ -68,7 +68,7 @@ I have not done this verification for ARM.
  build_rune_prefix=$2
  result_dir=$3
 
- git-clean -x -d -f
+ git clean -x -d -f
 
  cp "$our_config" .
 
@@ -109,7 +109,8 @@ I have not done this verification for ARM.
 
 -8<- function-filter -8<-
  #!/usr/bin/perl -w
- # for f in *.s; do ~/work/function-filter <$f >${f}2; done
+ # function-filter
+ # script for massaging gcc-generated labels to be consistent
  use strict;
  our @lines;
  my $sedderybody = "sub seddery () {\n";
@@ -126,19 +127,6 @@ I have not done this verification for ARM.
      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 +-
@@ -150,7 +138,7 @@ v2: Use Xen style for multi-line comments.
  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
+index e82f6e9..cc0f206 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,
@@ -165,7 +153,7 @@ index 8bd59ca..e481649 100644
      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,
+@@ -147,11 +147,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);
      }
  
@@ -181,7 +169,7 @@ index 8bd59ca..e481649 100644
             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,
+@@ -189,7 +189,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
      count = elf_shdr_count(&syms);
      for ( h = 0; h < count; h++ )
      {
@@ -190,7 +178,7 @@ index 8bd59ca..e481649 100644
          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,
+@@ -205,9 +205,9 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
              if ( i == count )
              {
                  if ( elf_64bit(&syms) )
@@ -202,7 +190,7 @@ index 8bd59ca..e481649 100644
                  continue;
              }
          }
-@@ -215,9 +215,9 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+@@ -216,9 +216,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) )
@@ -214,7 +202,7 @@ index 8bd59ca..e481649 100644
              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,
+@@ -230,7 +230,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
              if ( load )
              {
                  shdr2 = elf_shdr_by_index(elf, h);
@@ -223,7 +211,7 @@ index 8bd59ca..e481649 100644
                         elf_section_start(elf, shdr2),
                         size);
              }
-@@ -237,9 +237,9 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+@@ -238,9 +238,9 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
  
          /* Name is NULL. */
          if ( elf_64bit(&syms) )
@@ -235,7 +223,7 @@ index 8bd59ca..e481649 100644
      }
  
      if ( tables == 0 )
-@@ -274,7 +274,7 @@ static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
+@@ -275,7 +275,7 @@ static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
      }
  
      /* Find the section-header strings table. */
@@ -938,7 +926,7 @@ index 2f54142..f1fd886 100644
      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
+index 38e490c..cefd3d3 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,
@@ -1011,7 +999,7 @@ index 38e490c..bdfe323 100644
 +   * This macro provides a suitable cast.
 +   */
 +
-+#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
diff --git a/xsa55-4.20008-tools-xcutils-readnotes-adjust-print_l1_mfn_valid_no.patch b/xsa55-4.20009-tools-xcutils-readnotes-adjust-print_l1_mfn_valid_no.patch
similarity index 88%
rename from xsa55-4.20008-tools-xcutils-readnotes-adjust-print_l1_mfn_valid_no.patch
rename to xsa55-4.20009-tools-xcutils-readnotes-adjust-print_l1_mfn_valid_no.patch
index e18b410..707c570 100644
--- a/xsa55-4.20008-tools-xcutils-readnotes-adjust-print_l1_mfn_valid_no.patch
+++ b/xsa55-4.20009-tools-xcutils-readnotes-adjust-print_l1_mfn_valid_no.patch
@@ -1,7 +1,7 @@
-From 7fb404ee7c2ffa61f8d3be1a99cee1dcdcf87970 Mon Sep 17 00:00:00 2001
+From 59f66d58180832af6b99a9e4489031b5c2f627ab 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
+Date: Fri, 14 Jun 2013 16:43:17 +0100
+Subject: [PATCH 09/23] tools/xcutils/readnotes: adjust print_l1_mfn_valid_note
 
 Use the new PTRVAL macros and elf_access_unsigned in
 print_l1_mfn_valid_note.
@@ -12,10 +12,10 @@ file for a different endianness.
 Separated out from the previous patch because this change does produce
 a difference in the generated code.
 
+This is part of the fix to a security issue, XSA-55.
+
 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/xsa55-4.20009-libelf-check-nul-terminated-strings-properly.patch b/xsa55-4.20010-libelf-check-nul-terminated-strings-properly.patch
similarity index 93%
rename from xsa55-4.20009-libelf-check-nul-terminated-strings-properly.patch
rename to xsa55-4.20010-libelf-check-nul-terminated-strings-properly.patch
index 99487a6..b782936 100644
--- a/xsa55-4.20009-libelf-check-nul-terminated-strings-properly.patch
+++ b/xsa55-4.20010-libelf-check-nul-terminated-strings-properly.patch
@@ -1,7 +1,7 @@
-From 01ca8af5fdd11099bf2aebc68c528808729de56f Mon Sep 17 00:00:00 2001
+From db14d5bd9b6508adfcd2b910f454fae12fa4ba00 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
+Date: Fri, 14 Jun 2013 16:43:17 +0100
+Subject: [PATCH 10/23] 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
@@ -29,20 +29,20 @@ 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.
 
+This is part of the fix to a security issue, XSA-55.
+
 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 +++++++---
+ tools/xcutils/readnotes.c          |   11 ++++++++---
  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(-)
+ 4 files changed, 30 insertions(+), 11 deletions(-)
 
 diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
-index 7ff2530..ca86ba5 100644
+index 7ff2530..cfae994 100644
 --- a/tools/xcutils/readnotes.c
 +++ b/tools/xcutils/readnotes.c
 @@ -63,7 +63,7 @@ struct setup_header {
@@ -54,7 +54,7 @@ index 7ff2530..ca86ba5 100644
  }
  
  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,
+@@ -103,10 +103,14 @@ static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start,
  {
  	ELF_HANDLE_DECL(elf_note) note;
  	int notes_found = 0;
@@ -64,12 +64,13 @@ index 7ff2530..ca86ba5 100644
  	{
 -		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"))
++		if (NULL == this_note_name)
++			continue;
++		if (0 != strcmp(this_note_name, "Xen"))
  			continue;
  
  		notes_found++;
-@@ -294,7 +297,8 @@ int main(int argc, char **argv)
+@@ -294,7 +298,8 @@ int main(int argc, char **argv)
  
  	shdr = elf_shdr_by_name(&elf, "__xen_guest");
  	if (ELF_HANDLE_VALID(shdr))
@@ -167,7 +168,7 @@ index f1fd886..3a0cde1 100644
  
  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
+index cefd3d3..af5b5c5 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,
diff --git a/xsa55-4.20010-libelf-check-all-pointer-accesses.patch b/xsa55-4.20011-libelf-check-all-pointer-accesses.patch
similarity index 88%
rename from xsa55-4.20010-libelf-check-all-pointer-accesses.patch
rename to xsa55-4.20011-libelf-check-all-pointer-accesses.patch
index 3107064..5ad7827 100644
--- a/xsa55-4.20010-libelf-check-all-pointer-accesses.patch
+++ b/xsa55-4.20011-libelf-check-all-pointer-accesses.patch
@@ -1,7 +1,7 @@
-From bc14f1dd3f22d609a52edbe9b053180446e0068b Mon Sep 17 00:00:00 2001
+From cc8761371aac432318530c2ddfe2c8234bc0621f 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
+Date: Fri, 14 Jun 2013 16:43:17 +0100
+Subject: [PATCH 11/23] libelf: check all pointer accesses
 
 We change the ELF_PTRVAL and ELF_HANDLE types and associated macros:
 
@@ -80,75 +80,40 @@ We change the ELF_PTRVAL and ELF_HANDLE types and associated macros:
    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.
+This is part of the fix to a security issue, XSA-55.
 
 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_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(-)
+ xen/common/libelf/libelf-tools.c   |  106 ++++++++++++++++++-
+ xen/include/xen/libelf.h           |  198 +++++++++++++++++++++++++-----------
+ 8 files changed, 312 insertions(+), 85 deletions(-)
 
 diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
-index e481649..80152bf 100644
+index cc0f206..b82a08c 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,
+@@ -130,20 +130,30 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
  
      if ( load )
      {
+-        size_t allow_size; /* will be used in a forthcoming XSA-55 patch */
 +        char *hdr_ptr;
++        size_t allow_size;
 +
          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);
+-        hdr  = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start, &allow_size);
 -        *(int *)hdr = size - sizeof(int);
-+        hdr_ptr  = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start);
++        hdr_ptr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start, &allow_size);
 +        elf->caller_xdest_base = hdr_ptr;
-+        elf->caller_xdest_size = page_size -
-+            (dom->bsd_symtab_start & (page_size-1));
++        elf->caller_xdest_size = allow_size;
 +        hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
 +        elf_store_val(elf, int, hdr, size - sizeof(int));
      }
@@ -169,7 +134,7 @@ index e481649..80152bf 100644
          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,
+@@ -171,9 +181,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;
      }
@@ -203,7 +168,7 @@ index e481649..80152bf 100644
      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)
+@@ -312,8 +345,10 @@ static int xc_dom_load_elf_kernel(struct xc_dom_image *dom)
  {
      struct elf_binary *elf = dom->private_loader;
      int rc;
@@ -343,10 +308,10 @@ index 3ef753c..280dfd1 100644
  
  /*
 diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
-index 3a0cde1..ed107bc 100644
+index 3a0cde1..46ca553 100644
 --- a/xen/common/libelf/libelf-tools.c
 +++ b/xen/common/libelf/libelf-tools.c
-@@ -20,28 +20,97 @@
+@@ -20,28 +20,100 @@
  
  /* ------------------------------------------------------------------------ */
  
@@ -370,12 +335,15 @@ index 3a0cde1..ed107bc 100644
 +     * 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.
++     * region and regionsize are trusted and must be correct and valid,
++     * although it is OK for region to perhaps be maliciously NULL
++     * (but not some other malicious value).
 +     */
 +{
 +    elf_ptrval regionp = (elf_ptrval)region;
 +
-+    if ( (ptrval < regionp) ||              /* start is before region */
++    if ( (region == NULL) ||
++         (ptrval < regionp) ||              /* start is before region */
 +         (ptrval > regionp + regionsize) || /* start is after region */
 +         (size > regionsize - (ptrval - regionp)) ) /* too big */
 +        return 0;
@@ -450,7 +418,7 @@ index 3a0cde1..ed107bc 100644
          return need_swap ? bswap_64(*u64) : *u64;
      default:
          return 0;
-@@ -122,6 +191,28 @@ const char *elf_section_name(struct elf_binary *elf,
+@@ -122,6 +194,28 @@ const char *elf_section_name(struct elf_binary *elf,
      return elf_strval(elf, elf->sec_strtab + elf_uval(elf, shdr, sh_name));
  }
  
@@ -480,7 +448,7 @@ index 3a0cde1..ed107bc 100644
  {
      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
+index af5b5c5..ddc3ed7 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,
@@ -527,19 +495,19 @@ index 8049cdc..bbde92e 100644
 +#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"
++# 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.
++   * PRIuPTR is misdefined in xen/include/xen/inttypes.h, on 32-bit,
++   * to "u", when in fact uintptr_t is an unsigned long.
 +   */
 +#else
-+#define ELF_PRPTRVAL PRIuPTR
++# define ELF_PRPTRVAL PRIuPTR
 +#endif
-+
++  /* printf format a la PRId... for a PTRVAL */
+ 
+-#define ELF_DEFINE_HANDLE(structname) /* empty */
 +#define ELF_DEFINE_HANDLE(structname)                                   \
 +    typedef union {                                                     \
 +        elf_ptrval ptrval;                                              \
@@ -579,12 +547,12 @@ index 8049cdc..bbde92e 100644
 +   * and no need for any casting.
     */
  
--#define ELF_UNSAFE_PTR(ptrval) ((void*)(ptrval))
-+#define ELF_UNSAFE_PTR(ptrval) ((void*)(uintptr_t)(ptrval))
+-#define ELF_UNSAFE_PTR(ptrval) ((void*)(uintptr_t)(ptrval))
++#define ELF_UNSAFE_PTR(ptrval) ((void*)(elf_ptrval)(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,
+@@ -122,18 +135,21 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
     */
  
  /* PTRVALs can be INVALID (ie, NULL). */
@@ -612,12 +580,7 @@ index 8049cdc..bbde92e 100644
  
  
  /* ------------------------------------------------------------------------ */
- 
--
- typedef union {
-     Elf32_Ehdr e32;
-     Elf64_Ehdr e64;
-@@ -182,7 +197,7 @@ ELF_DEFINE_HANDLE(elf_note)
+@@ -182,7 +198,7 @@ ELF_DEFINE_HANDLE(elf_note)
  
  struct elf_binary {
      /* elf binary */
@@ -626,7 +589,7 @@ index 8049cdc..bbde92e 100644
      size_t size;
      char class;
      char data;
-@@ -190,10 +205,16 @@ struct elf_binary {
+@@ -190,10 +206,16 @@ struct elf_binary {
      ELF_HANDLE_DECL(elf_ehdr) ehdr;
      ELF_PTRVAL_CONST_CHAR sec_strtab;
      ELF_HANDLE_DECL(elf_shdr) sym_tab;
@@ -645,7 +608,7 @@ index 8049cdc..bbde92e 100644
      uint64_t pstart;
      uint64_t pend;
      uint64_t reloc_offset;
-@@ -201,12 +222,22 @@ struct elf_binary {
+@@ -201,12 +223,22 @@ struct elf_binary {
      uint64_t bsd_symtab_pstart;
      uint64_t bsd_symtab_pend;
  
@@ -668,7 +631,7 @@ index 8049cdc..bbde92e 100644
  };
  
  /* ------------------------------------------------------------------------ */
-@@ -224,22 +255,27 @@ struct elf_binary {
+@@ -224,22 +256,27 @@ struct elf_binary {
  #define elf_lsb(elf)   (ELFDATA2LSB == (elf)->data)
  #define elf_swap(elf)  (NATIVE_ELFDATA != (elf)->data)
  
@@ -706,7 +669,7 @@ index 8049cdc..bbde92e 100644
    /*
     * 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,
+@@ -251,23 +288,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);
  
@@ -754,7 +717,7 @@ index 8049cdc..bbde92e 100644
                     (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)
+@@ -306,6 +357,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);
@@ -765,7 +728,7 @@ index 8049cdc..bbde92e 100644
  #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);
+@@ -321,6 +376,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 */
  
@@ -775,7 +738,7 @@ index 8049cdc..bbde92e 100644
  /* ------------------------------------------------------------------------ */
  /* xc_libelf_relocate.c                                                     */
  
-@@ -395,16 +452,33 @@ int elf_xen_parse_guest_info(struct elf_binary *elf,
+@@ -395,16 +453,38 @@ int elf_xen_parse_guest_info(struct elf_binary *elf,
  int elf_xen_parse(struct elf_binary *elf,
                    struct elf_dom_parms *parms);
  
@@ -802,7 +765,11 @@ index 8049cdc..bbde92e 100644
 +/* 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 )
++    if ( elf->dest_base == NULL )
++    {
++        elf_mark_broken(elf, "advancing in null image");
++    }
++    else if ( elf->dest_size >= amount )
 +    {
 +        elf->dest_base += amount;
 +        elf->dest_size -= amount;
@@ -810,6 +777,7 @@ index 8049cdc..bbde92e 100644
 +    else
 +    {
 +        elf->dest_size = 0;
++        elf_mark_broken(elf, "advancing past end (image very short?)");
 +    }
 +}
  
diff --git a/xsa55-4.20011-libelf-Check-pointer-references-in-elf_is_elfbinary.patch b/xsa55-4.20012-libelf-Check-pointer-references-in-elf_is_elfbinary.patch
similarity index 80%
rename from xsa55-4.20011-libelf-Check-pointer-references-in-elf_is_elfbinary.patch
rename to xsa55-4.20012-libelf-Check-pointer-references-in-elf_is_elfbinary.patch
index a91fac0..cefb4cb 100644
--- a/xsa55-4.20011-libelf-Check-pointer-references-in-elf_is_elfbinary.patch
+++ b/xsa55-4.20012-libelf-Check-pointer-references-in-elf_is_elfbinary.patch
@@ -1,27 +1,31 @@
-From eb40af0a209a3778fe39737bb44fdc2b6d3c6b92 Mon Sep 17 00:00:00 2001
+From d0790bdad7496e720416b2d4a04563c4c27e7b95 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
+Date: Fri, 14 Jun 2013 16:43:17 +0100
+Subject: [PATCH 12/23] 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.
 
+We only need to check the size is enough for the actual dereference in
+elf_is_elfbinary; callers are just using it to check the magic number
+and do their own checks (usually via the new elf_ptrval system) before
+dereferencing other parts of the header.
+
+This is part of the fix to a security issue, XSA-55.
+
 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(-)
+ xen/include/xen/libelf.h          |    4 +++-
+ 5 files changed, 13 insertions(+), 8 deletions(-)
 
 diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
-index 80152bf..92211bd 100644
+index b82a08c..ea45886 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)
@@ -69,10 +73,10 @@ index a3310e7..f8be635 100644
          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
+index 46ca553..744027e 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(
+@@ -332,11 +332,14 @@ ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(
  
  /* ------------------------------------------------------------------------ */
  
@@ -91,15 +95,17 @@ index ed107bc..9c13377 100644
  
  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
+index ddc3ed7..ac93858 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),
+@@ -350,7 +350,9 @@ 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);
++/* (Only) checks that the image has the right magic number. */
 +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);
  
  /* ------------------------------------------------------------------------ */
diff --git a/xsa55-4.20012-libelf-Make-all-callers-call-elf_check_broken.patch b/xsa55-4.20013-libelf-Make-all-callers-call-elf_check_broken.patch
similarity index 89%
rename from xsa55-4.20012-libelf-Make-all-callers-call-elf_check_broken.patch
rename to xsa55-4.20013-libelf-Make-all-callers-call-elf_check_broken.patch
index 97b5cb4..43fe7f0 100644
--- a/xsa55-4.20012-libelf-Make-all-callers-call-elf_check_broken.patch
+++ b/xsa55-4.20013-libelf-Make-all-callers-call-elf_check_broken.patch
@@ -1,7 +1,7 @@
-From 87c02b2160cbaf81c37b904d2e651bcdff149939 Mon Sep 17 00:00:00 2001
+From a965b8f80388603d439ae2b8ee7b9b018a079f90 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
+Date: Fri, 14 Jun 2013 16:43:17 +0100
+Subject: [PATCH 13/23] 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
@@ -15,16 +15,17 @@ 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>
+Difference in the 4.2 series, compared to unstable:
+
+* tools/libxc/xc_hvm_build_x86.c:setup_guest and
+  xen/arch/arm/kernel.c:kernel_try_elf_prepare have different
+  error handling in 4.2 to unstable; patch adjusted accordingly.
 
-v3.1:
-    Add error check to xc_dom_parse_elf_kernel.
-    Move check in xc_hvm_build_x86.c:setup_guest to right place.
+This is part of the fix to a security issue, XSA-55.
 
-v2 Acked-by: Ian Campbell <ian.campbell at citrix.com>
-v2 Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk at oracle.com>
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
 
-v2: Style fixes.
+xen-unstable version Reviewed-by: George Dunlap <george.dunlap at eu.citrix.com>
 ---
  tools/libxc/xc_dom_elfloader.c |   25 +++++++++++++++++++++----
  tools/libxc/xc_hvm_build_x86.c |    5 +++++
@@ -34,10 +35,10 @@ v2: Style fixes.
  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
+index ea45886..4fb4da2 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,
+@@ -276,6 +276,13 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
              elf_store_field(elf, shdr, e32.sh_name, 0);
      }
  
@@ -51,7 +52,7 @@ index 92211bd..c7958ec 100644
      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)
+@@ -312,19 +319,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__);
@@ -78,7 +79,7 @@ index 92211bd..c7958ec 100644
      }
  
      /* find kernel segment */
-@@ -339,7 +350,13 @@ static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
+@@ -338,7 +349,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);
@@ -88,7 +89,7 @@ index 92211bd..c7958ec 100644
 +    if ( elf_check_broken(elf) )
 +        DOMPRINTF("%s: ELF broken: %s", __FUNCTION__,
 +                  elf_check_broken(elf));
-+    
++
 +    return rc;
  }
  
@@ -115,14 +116,14 @@ index ccfd8b5..8165287 100644
  }
  
 diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
-index ca86ba5..b868fba 100644
+index cfae994..d1f7a30 100644
 --- a/tools/xcutils/readnotes.c
 +++ b/tools/xcutils/readnotes.c
-@@ -300,6 +300,9 @@ int main(int argc, char **argv)
+@@ -301,6 +301,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))
++	if (elf_check_broken(&elf))
 +		printf("warning: broken ELF: %s\n", elf_check_broken(&elf));
 +
  	return 0;
diff --git a/xsa55-4.20013-libelf-use-C99-bool-for-booleans.patch b/xsa55-4.20014-libelf-use-C99-bool-for-booleans.patch
similarity index 90%
rename from xsa55-4.20013-libelf-use-C99-bool-for-booleans.patch
rename to xsa55-4.20014-libelf-use-C99-bool-for-booleans.patch
index e9c852b..67990a2 100644
--- a/xsa55-4.20013-libelf-use-C99-bool-for-booleans.patch
+++ b/xsa55-4.20014-libelf-use-C99-bool-for-booleans.patch
@@ -1,7 +1,7 @@
-From ad1886e0b717d5455e57ac8c0556ddfac334f0e7 Mon Sep 17 00:00:00 2001
+From 3fb6ccf2faccaf5e22e33a3155ccc72d732896d8 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
+Date: Fri, 14 Jun 2013 16:43:18 +0100
+Subject: [PATCH 14/23] 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
@@ -25,10 +25,10 @@ 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>
+This is part of the fix to a security issue, XSA-55.
 
-v3: Use <stdbool.h>'s bool (or _Bool) instead of defining elf_bool.
-    Split this into a separate patch.
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+Acked-by: George Dunlap <george.dunlap at eu.citrix.com>
 ---
  tools/libxc/xc_dom_elfloader.c     |    8 ++++----
  xen/common/libelf/libelf-dominfo.c |    2 +-
@@ -39,7 +39,7 @@ v3: Use <stdbool.h>'s bool (or _Bool) instead of defining elf_bool.
  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
+index 4fb4da2..9ba64ae 100644
 --- a/tools/libxc/xc_dom_elfloader.c
 +++ b/tools/libxc/xc_dom_elfloader.c
 @@ -34,7 +34,7 @@
@@ -127,7 +127,7 @@ index 280dfd1..277be04 100644
  #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
+index 744027e..fa58f76 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)
@@ -139,7 +139,7 @@ index 9c13377..ac6438f 100644
                                 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,
+@@ -53,7 +53,7 @@ static int elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
      return 1;
  }
  
@@ -148,7 +148,7 @@ index 9c13377..ac6438f 100644
                    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,
+@@ -92,7 +92,7 @@ uint64_t elf_access_unsigned(struct elf_binary * elf, elf_ptrval base,
                               uint64_t moreoffset, size_t size)
  {
      elf_ptrval ptrval = base + moreoffset;
@@ -157,7 +157,7 @@ index 9c13377..ac6438f 100644
      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(
+@@ -332,7 +332,7 @@ ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(
  
  /* ------------------------------------------------------------------------ */
  
@@ -166,7 +166,7 @@ index 9c13377..ac6438f 100644
  {
      const Elf32_Ehdr *ehdr = image_start;
  
-@@ -339,7 +339,7 @@ int elf_is_elfbinary(const void *image_start, size_t image_size)
+@@ -342,7 +342,7 @@ int elf_is_elfbinary(const void *image_start, size_t image_size)
      return IS_ELF(*ehdr);
  }
  
@@ -176,7 +176,7 @@ index 9c13377..ac6438f 100644
      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
+index ac93858..951430f 100644
 --- a/xen/include/xen/libelf.h
 +++ b/xen/include/xen/libelf.h
 @@ -29,6 +29,8 @@
@@ -197,7 +197,7 @@ index 12d77f9..22febea 100644
  
  #endif
  
-@@ -236,7 +238,7 @@ struct elf_binary {
+@@ -237,7 +239,7 @@ struct elf_binary {
      elf_log_callback *log_callback;
      void *log_caller_data;
  #endif
@@ -206,7 +206,7 @@ index 12d77f9..22febea 100644
      const char *broken;
  };
  
-@@ -300,8 +302,8 @@ void elf_memset_safe(struct elf_binary*, elf_ptrval dst, int c, size_t);
+@@ -301,8 +303,8 @@ void elf_memset_safe(struct elf_binary*, elf_ptrval dst, int c, size_t);
     * outside permitted areas.
     */
  
@@ -217,18 +217,19 @@ index 12d77f9..22febea 100644
  
  #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);
+@@ -351,9 +353,9 @@ uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
  ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
  
+ /* (Only) checks that the image has the right magic number. */
 -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);
+ 
+-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);
  
  /* ------------------------------------------------------------------------ */
  /* xc_libelf_loader.c                                                       */
-@@ -364,7 +366,7 @@ int elf_init(struct elf_binary *elf, const char *image, size_t size);
+@@ -367,7 +369,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*,
@@ -237,7 +238,7 @@ index 12d77f9..22febea 100644
  #endif
  
  void elf_parse_binary(struct elf_binary *elf);
-@@ -416,7 +418,7 @@ struct elf_dom_parms {
+@@ -419,7 +421,7 @@ struct elf_dom_parms {
      char xen_ver[16];
      char loader[16];
      int pae;
diff --git a/xsa55-4.20014-libelf-use-only-unsigned-integers.patch b/xsa55-4.20015-libelf-use-only-unsigned-integers.patch
similarity index 89%
rename from xsa55-4.20014-libelf-use-only-unsigned-integers.patch
rename to xsa55-4.20015-libelf-use-only-unsigned-integers.patch
index 361cce8..f55701d 100644
--- a/xsa55-4.20014-libelf-use-only-unsigned-integers.patch
+++ b/xsa55-4.20015-libelf-use-only-unsigned-integers.patch
@@ -1,7 +1,7 @@
-From 2238fd744ab359dc82e6299629fdf442a197bee3 Mon Sep 17 00:00:00 2001
+From e673ca50127b6c1263727aa31de0b8bb966ca7a2 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
+Date: Fri, 14 Jun 2013 16:43:18 +0100
+Subject: [PATCH 15/23] libelf: use only unsigned integers
 
 Signed integers have undesirable undefined behaviours on overflow.
 Malicious compilers can turn apparently-correct code into code with
@@ -29,6 +29,8 @@ 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").
 
+This is part of the fix to a security issue, XSA-55.
+
 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:
@@ -57,27 +59,17 @@ this patch, and unsigned-differ is this shell script:
     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 ++++++-----
+ tools/xcutils/readnotes.c          |   15 +++++-----
  xen/common/libelf/Makefile         |    2 +
- xen/common/libelf/libelf-dominfo.c |   50 ++++++++++++++++++------------------
+ xen/common/libelf/libelf-dominfo.c |   52 ++++++++++++++++++-----------------
  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(-)
+ 9 files changed, 105 insertions(+), 87 deletions(-)
 
 diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
 index d8c6a60..a3fd90c 100644
@@ -100,7 +92,7 @@ index d8c6a60..a3fd90c 100644
  # 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
+index 9f8037e..0161459 100644
 --- a/tools/libxc/xc_dom.h
 +++ b/tools/libxc/xc_dom.h
 @@ -140,9 +140,10 @@ struct xc_dom_image {
@@ -118,7 +110,7 @@ index b74252f..eb02c25 100644
      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
+index 9ba64ae..62a0d3b 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,
@@ -151,12 +143,12 @@ index 3738250..d9b1a43 100644
      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));
+     {
+@@ -140,13 +140,13 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+         elf->caller_xdest_base = hdr_ptr;
+         elf->caller_xdest_size = allow_size;
          hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
 -        elf_store_val(elf, int, hdr, size - sizeof(int));
 +        elf_store_val(elf, unsigned, hdr, size - sizeof(unsigned));
@@ -170,7 +162,7 @@ index 3738250..d9b1a43 100644
              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,
+@@ -157,15 +157,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);
      }
  
@@ -189,7 +181,7 @@ index 3738250..d9b1a43 100644
          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,
+@@ -174,22 +174,22 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
      }
      else
      {
@@ -216,7 +208,7 @@ index 3738250..d9b1a43 100644
          return -1;
  
      /*
-@@ -210,7 +210,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+@@ -209,7 +209,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
  
      xc_elf_set_logfile(dom->xch, &syms, 1);
  
@@ -225,7 +217,7 @@ index 3738250..d9b1a43 100644
      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,
+@@ -255,7 +255,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++;
@@ -234,7 +226,7 @@ index 3738250..d9b1a43 100644
                        __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,
+@@ -294,10 +294,14 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
      return 0;
  }
  
@@ -242,7 +234,7 @@ index 3738250..d9b1a43 100644
 +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?
++     * an errno value.  ?!?!
 +     */
  {
      struct elf_binary *elf;
@@ -251,7 +243,7 @@ index 3738250..d9b1a43 100644
  
      rc = check_elf_kernel(dom, 1);
      if ( rc != 0 )
-@@ -359,10 +363,10 @@ out:
+@@ -358,10 +362,10 @@ out:
      return rc;
  }
  
@@ -265,7 +257,7 @@ index 3738250..d9b1a43 100644
  
      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
+index d1f7a30..2ca7732 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,
@@ -299,7 +291,7 @@ index b868fba..9be1594 100644
  	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,
+@@ -161,7 +161,7 @@ static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start,
  			break;
  		default:
  			printf("unknown note type %#x\n",
@@ -308,7 +300,7 @@ index b868fba..9be1594 100644
  			break;
  		}
  	}
-@@ -170,12 +170,13 @@ static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start,
+@@ -171,12 +171,13 @@ static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start,
  int main(int argc, char **argv)
  {
  	const char *f;
@@ -338,7 +330,7 @@ index 18dc8e2..5bf8f76 100644
  	$(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
+index 12b6c2a..cdd0d31 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[] = {
@@ -379,11 +371,13 @@ index 12b6c2a..e837d4d 100644
  
      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,
+@@ -216,12 +216,14 @@ int elf_xen_parse_note(struct elf_binary *elf,
      return 0;
  }
  
 -static int elf_xen_parse_notes(struct elf_binary *elf,
++#define ELF_NOTE_INVALID (~0U)
++
 +static unsigned elf_xen_parse_notes(struct elf_binary *elf,
                                 struct elf_dom_parms *parms,
                                 ELF_PTRVAL_CONST_VOID start,
@@ -394,16 +388,16 @@ index 12b6c2a..e837d4d 100644
      ELF_HANDLE_DECL(elf_note) note;
      const char *note_name;
  
-@@ -237,7 +237,7 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
+@@ -237,7 +239,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;
++            return ELF_NOTE_INVALID;
          xen_elfnotes++;
      }
      return xen_elfnotes;
-@@ -246,12 +246,12 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
+@@ -246,12 +248,12 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
  /* ------------------------------------------------------------------------ */
  /* __xen_guest section                                                      */
  
@@ -419,7 +413,7 @@ index 12b6c2a..e837d4d 100644
  
      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,
+@@ -334,13 +336,13 @@ int elf_xen_parse_guest_info(struct elf_binary *elf,
  /* ------------------------------------------------------------------------ */
  /* sanity checks                                                            */
  
@@ -435,7 +429,7 @@ index 12b6c2a..e837d4d 100644
          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,
+@@ -378,7 +380,7 @@ static int elf_xen_note_check(struct elf_binary *elf,
      return 0;
  }
  
@@ -444,7 +438,7 @@ index 12b6c2a..e837d4d 100644
                                     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,
+@@ -464,13 +466,13 @@ static int elf_xen_addr_calc_check(struct elf_binary *elf,
  /* ------------------------------------------------------------------------ */
  /* glue it all together ...                                                 */
  
@@ -461,7 +455,7 @@ index 12b6c2a..e837d4d 100644
  
      elf_memset_unchecked(parms, 0, sizeof(*parms));
      parms->virt_base = UNSET_ADDR;
-@@ -495,13 +495,13 @@ int elf_xen_parse(struct elf_binary *elf,
+@@ -495,13 +497,13 @@ int elf_xen_parse(struct elf_binary *elf,
          if (elf_uval(elf, phdr, p_offset) == 0)
               continue;
  
@@ -470,7 +464,7 @@ index 12b6c2a..e837d4d 100644
                                   elf_segment_start(elf, phdr),
                                   elf_segment_end(elf, phdr));
 -        if ( rc == -1 )
-+        if ( more_notes == ~0U )
++        if ( more_notes == ELF_NOTE_INVALID )
              return -1;
  
 -        xen_elfnotes += rc;
@@ -478,7 +472,7 @@ index 12b6c2a..e837d4d 100644
      }
  
      /*
-@@ -518,17 +518,17 @@ int elf_xen_parse(struct elf_binary *elf,
+@@ -518,17 +520,17 @@ int elf_xen_parse(struct elf_binary *elf,
              if ( elf_uval(elf, shdr, sh_type) != SHT_NOTE )
                  continue;
  
@@ -488,7 +482,7 @@ index 12b6c2a..e837d4d 100644
                                       elf_section_end(elf, shdr));
  
 -            if ( rc == -1 )
-+            if ( more_notes == ~0U )
++            if ( more_notes == ELF_NOTE_INVALID )
                  return -1;
  
 -            if ( xen_elfnotes == 0 && rc > 0 )
@@ -584,15 +578,15 @@ index 0dccd4d..c3a9e51 100644
      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
+index fa58f76..46d4ab1 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,
+@@ -122,19 +122,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;
++    uint64_t elf_round = (elf_64bit(elf) ? 8 : 4) - 1;
  
      return (addr + elf_round) & ~elf_round;
  }
@@ -610,7 +604,7 @@ index ac6438f..308ea15 100644
  {
      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
+@@ -144,7 +144,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;
@@ -619,7 +613,7 @@ index ac6438f..308ea15 100644
  
      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
+@@ -156,7 +156,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
      return ELF_INVALID_HANDLE(elf_shdr);
  }
  
@@ -628,7 +622,7 @@ index ac6438f..308ea15 100644
  {
      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)
+@@ -170,7 +170,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index)
      return ELF_MAKE_HANDLE(elf_shdr, ptr);
  }
  
@@ -637,7 +631,7 @@ index ac6438f..308ea15 100644
  {
      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
+@@ -264,7 +264,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym
      return ELF_INVALID_HANDLE(elf_sym);
  }
  
@@ -646,7 +640,7 @@ index ac6438f..308ea15 100644
  {
      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
+@@ -280,7 +280,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)
  {
@@ -655,7 +649,7 @@ index ac6438f..308ea15 100644
  
      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_
+@@ -288,7 +288,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);
@@ -664,7 +658,7 @@ index ac6438f..308ea15 100644
  
      switch (descsz)
      {
-@@ -303,7 +303,7 @@ uint64_t elf_note_numeric_array(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note
+@@ -306,7 +306,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);
@@ -673,7 +667,7 @@ index ac6438f..308ea15 100644
  
      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
+@@ -324,8 +324,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)
  {
@@ -685,7 +679,7 @@ index ac6438f..308ea15 100644
      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
+index 951430f..87e126a 100644
 --- a/xen/include/xen/libelf.h
 +++ b/xen/include/xen/libelf.h
 @@ -31,6 +31,9 @@
@@ -698,7 +692,7 @@ index 22febea..4fc2496 100644
  #undef ELFSIZE
  #include "elfstructs.h"
  #ifdef __XEN__
-@@ -327,12 +330,12 @@ bool elf_access_ok(struct elf_binary * elf,
+@@ -328,12 +331,12 @@ bool elf_access_ok(struct elf_binary * elf,
  /* ------------------------------------------------------------------------ */
  /* xc_libelf_tools.c                                                        */
  
@@ -715,7 +709,7 @@ index 22febea..4fc2496 100644
  
  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(
+@@ -343,7 +346,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);
@@ -724,7 +718,7 @@ index 22febea..4fc2496 100644
  
  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
+@@ -360,7 +363,7 @@ bool elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr
  /* ------------------------------------------------------------------------ */
  /* xc_libelf_loader.c                                                       */
  
@@ -733,7 +727,7 @@ index 22febea..4fc2496 100644
    /*
     * 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*,
+@@ -373,7 +376,7 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback*,
  #endif
  
  void elf_parse_binary(struct elf_binary *elf);
@@ -742,7 +736,7 @@ index 22febea..4fc2496 100644
  
  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 */
+@@ -386,7 +389,7 @@ const char *elf_check_broken(const struct elf_binary *elf); /* NULL means OK */
  /* ------------------------------------------------------------------------ */
  /* xc_libelf_relocate.c                                                     */
  
@@ -751,7 +745,7 @@ index 22febea..4fc2496 100644
  
  /* ------------------------------------------------------------------------ */
  /* xc_libelf_dominfo.c                                                      */
-@@ -417,7 +420,7 @@ struct elf_dom_parms {
+@@ -420,7 +423,7 @@ struct elf_dom_parms {
      char guest_ver[16];
      char xen_ver[16];
      char loader[16];
diff --git a/xsa55-4.20016-libelf-check-loops-for-running-away.patch b/xsa55-4.20016-libelf-check-loops-for-running-away.patch
new file mode 100644
index 0000000..fe09e46
--- /dev/null
+++ b/xsa55-4.20016-libelf-check-loops-for-running-away.patch
@@ -0,0 +1,409 @@
+From 52d8cc2dd3bb3e0f6d51e00280da934e8d91653a Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 14 Jun 2013 16:43:18 +0100
+Subject: [PATCH 16/23] 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.  Also check that the returned psuedopointer is sane.
+ * 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.
+ * Some fixed limits to avoid potentially O(image_size^2) loops:
+    - maximum length of strings: 4K (longer ones ignored totally)
+    - maximum total number of ELF notes: 65536 (any more are ignored)
+ * Check that the total program contents (text, data) we copy or
+   initialise doesn't exceed twice the output image area size.
+ * Remove an entirely useless loop from elf_xen_parse (!)
+ * Replace a nested search loop in in xc_dom_load_elf_symtab in
+   xc_dom_elfloader.c by a precomputation of a bitmap of referenced
+   symtabs.
+
+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.
+
+This is part of the fix to a security issue, XSA-55.
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+---
+ tools/libxc/xc_dom_elfloader.c     |   33 ++++++++++++++++++-------
+ xen/common/libelf/libelf-dominfo.c |   43 ++++++++++++++++++++------------
+ xen/common/libelf/libelf-loader.c  |   47 ++++++++++++++++++++++++++++++++++-
+ xen/common/libelf/libelf-tools.c   |   28 ++++++++++++++++++++-
+ xen/include/xen/libelf.h           |   13 ++++++++++
+ 5 files changed, 135 insertions(+), 29 deletions(-)
+
+diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
+index 62a0d3b..c5014d2 100644
+--- a/tools/libxc/xc_dom_elfloader.c
++++ b/tools/libxc/xc_dom_elfloader.c
+@@ -28,6 +28,7 @@
+ 
+ #include "xg_private.h"
+ #include "xc_dom.h"
++#include "xc_bitops.h"
+ 
+ #define XEN_VER "xen-3.0"
+ 
+@@ -120,6 +121,7 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+     ELF_PTRVAL_CHAR hdr;
+     size_t size;
+     unsigned h, count, type, i, tables = 0;
++    unsigned long *strtab_referenced = NULL;
+ 
+     if ( elf_swap(elf) )
+     {
+@@ -220,22 +222,35 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+               symtab, maxaddr);
+ 
+     count = elf_shdr_count(&syms);
++    /* elf_shdr_count guarantees that count is reasonable */
++
++    strtab_referenced = xc_dom_malloc(dom, bitmap_size(count));
++    if ( strtab_referenced == NULL )
++        return -1;
++    bitmap_clear(strtab_referenced, count);
++    /* Note the symtabs @h linked to by any strtab @i. */
++    for ( i = 0; i < count; i++ )
++    {
++        shdr2 = elf_shdr_by_index(&syms, i);
++        if ( elf_uval(&syms, shdr2, sh_type) == SHT_SYMTAB )
++        {
++            h = elf_uval(&syms, shdr2, sh_link);
++            if (h < count)
++                set_bit(h, strtab_referenced);
++        }
++    }
++
+     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 )
+         {
+-            /* Look for a strtab @i linked to symtab @h. */
+-            for ( i = 0; i < count; i++ )
+-            {
+-                shdr2 = elf_shdr_by_index(&syms, i);
+-                if ( (elf_uval(&syms, shdr2, sh_type) == SHT_SYMTAB) &&
+-                     (elf_uval(&syms, shdr2, sh_link) == h) )
+-                    break;
+-            }
+             /* Skip symtab @h if we found no corresponding strtab @i. */
+-            if ( i == count )
++            if ( !test_bit(h, strtab_referenced) )
+             {
+                 if ( elf_64bit(&syms) )
+                     elf_store_field(elf, shdr, e64.sh_offset, 0);
+diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
+index cdd0d31..25a10d7 100644
+--- a/xen/common/libelf/libelf-dominfo.c
++++ b/xen/common/libelf/libelf-dominfo.c
+@@ -221,7 +221,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_CONST_VOID end,
++                               unsigned *total_note_count)
+ {
+     unsigned xen_elfnotes = 0;
+     ELF_HANDLE_DECL(elf_note) note;
+@@ -233,6 +234,12 @@ static unsigned elf_xen_parse_notes(struct elf_binary *elf,
+           ELF_HANDLE_PTRVAL(note) < parms->elf_note_end;
+           note = elf_note_next(elf, note) )
+     {
++        if ( *total_note_count >= ELF_MAX_TOTAL_NOTE_COUNT )
++        {
++            elf_mark_broken(elf, "too many ELF notes");
++            break;
++        }
++        (*total_note_count)++;
+         note_name = elf_note_name(elf, note);
+         if ( note_name == NULL )
+             continue;
+@@ -473,6 +480,7 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
+     ELF_HANDLE_DECL(elf_phdr) phdr;
+     unsigned xen_elfnotes = 0;
+     unsigned i, count, more_notes;
++    unsigned total_note_count = 0;
+ 
+     elf_memset_unchecked(parms, 0, sizeof(*parms));
+     parms->virt_base = UNSET_ADDR;
+@@ -487,6 +495,9 @@ elf_errorstatus elf_xen_parse(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_uval(elf, phdr, p_type) != PT_NOTE )
+             continue;
+ 
+@@ -499,7 +510,8 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
+ 
+         more_notes = elf_xen_parse_notes(elf, parms,
+                                  elf_segment_start(elf, phdr),
+-                                 elf_segment_end(elf, phdr));
++                                 elf_segment_end(elf, phdr),
++                                 &total_note_count);
+         if ( more_notes == ELF_NOTE_INVALID )
+             return -1;
+ 
+@@ -516,13 +528,17 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
+         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_NOTE )
+                 continue;
+ 
+             more_notes = elf_xen_parse_notes(elf, parms,
+                                      elf_section_start(elf, shdr),
+-                                     elf_section_end(elf, shdr));
++                                     elf_section_end(elf, shdr),
++                                     &total_note_count);
+ 
+             if ( more_notes == ELF_NOTE_INVALID )
+                 return -1;
+@@ -540,20 +556,15 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
+      */
+     if ( xen_elfnotes == 0 )
+     {
+-        count = elf_shdr_count(elf);
+-        for ( i = 0; i < count; i++ )
++        shdr = elf_shdr_by_name(elf, "__xen_guest");
++        if ( ELF_HANDLE_VALID(shdr) )
+         {
+-            shdr = elf_shdr_by_name(elf, "__xen_guest");
+-            if ( ELF_HANDLE_VALID(shdr) )
+-            {
+-                parms->guest_info = elf_section_start(elf, shdr);
+-                parms->elf_note_start = ELF_INVALID_PTRVAL;
+-                parms->elf_note_end   = ELF_INVALID_PTRVAL;
+-                elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__,
+-                        elf_strfmt(elf, parms->guest_info));
+-                elf_xen_parse_guest_info(elf, parms);
+-                break;
+-            }
++            parms->guest_info = elf_section_start(elf, shdr);
++            parms->elf_note_start = ELF_INVALID_PTRVAL;
++            parms->elf_note_end   = ELF_INVALID_PTRVAL;
++            elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__,
++                    elf_strfmt(elf, 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 c3a9e51..06799af 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);
+@@ -278,11 +298,20 @@ 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;
++    /*
++     * Let bizarre ELFs write the output image up to twice; this
++     * calculation is just to ensure our copying loop is no worse than
++     * O(domain_size).
++     */
++    uint64_t remain_allow_copy = (uint64_t)elf->dest_size * 2;
+ 
+     count = elf_uval(elf, elf->ehdr, e_phnum);
+     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);
+@@ -290,6 +319,20 @@ elf_errorstatus 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);
++
++        /*
++         * We need to check that the input image doesn't have us copy
++         * the whole image zillions of times, as that could lead to
++         * O(n^2) time behaviour and possible DoS by a malicous ELF.
++         */
++        if ( remain_allow_copy < memsz )
++        {
++            elf_mark_broken(elf, "program segments total to more"
++                            " than the input image size");
++            break;
++        }
++        remain_allow_copy -= memsz;
++
+         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 )
+diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
+index 46d4ab1..4a83133 100644
+--- a/xen/common/libelf/libelf-tools.c
++++ b/xen/common/libelf/libelf-tools.c
+@@ -131,7 +131,16 @@ uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr)
+ 
+ unsigned elf_shdr_count(struct elf_binary *elf)
+ {
+-    return elf_uval(elf, elf->ehdr, e_shnum);
++    unsigned count = elf_uval(elf, elf->ehdr, e_shnum);
++    uint64_t max = elf->size / sizeof(Elf32_Shdr);
++    if (max > ~(unsigned)0)
++        max = ~(unsigned)0; /* Xen doesn't have limits.h :-/ */
++    if (count > max)
++    {
++        elf_mark_broken(elf, "far too many section headers");
++        count = max;
++    }
++    return count;
+ }
+ 
+ unsigned elf_phdr_count(struct elf_binary *elf)
+@@ -149,6 +158,9 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
+     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;
+         sname = elf_section_name(elf, shdr);
+         if ( sname && !strcmp(sname, name) )
+             return shdr;
+@@ -204,6 +216,11 @@ const char *elf_strval(struct elf_binary *elf, elf_ptrval start)
+         if ( !elf_access_unsigned(elf, start, length, 1) )
+             /* ok */
+             return ELF_UNSAFE_PTR(start);
++        if ( length >= ELF_MAX_STRING_LENGTH )
++        {
++            elf_mark_broken(elf, "excessively long string");
++            return NULL;
++        }
+     }
+ }
+ 
+@@ -327,7 +344,14 @@ 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) || /* wrapped or stuck */
++           !elf_access_ok(elf, ELF_HANDLE_PTRVAL(note), 1) ) )
++        ptrval = ELF_MAX_PTRVAL; /* terminate caller's loop */
++
++    return ELF_MAKE_HANDLE(elf_note, ptrval);
+ }
+ 
+ /* ------------------------------------------------------------------------ */
+diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
+index 87e126a..f95fe88 100644
+--- a/xen/include/xen/libelf.h
++++ b/xen/include/xen/libelf.h
+@@ -51,6 +51,9 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
+ 
+ #endif
+ 
++#define ELF_MAX_STRING_LENGTH 4096
++#define ELF_MAX_TOTAL_NOTE_COUNT 65536
++
+ /* ------------------------------------------------------------------------ */
+ 
+ /* Macros for accessing the input image and output area. */
+@@ -353,6 +356,16 @@ 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);
+ uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
+                                 unsigned int unitsz, unsigned int idx);
++
++/*
++ * If you use elf_note_next in a loop, you must put a nontrivial upper
++ * bound on the returned value as part of your loop condition.  In
++ * some cases elf_note_next will substitute ELF_PTRVAL_MAX as return
++ * value to indicate that the iteration isn't going well (for example,
++ * the putative "next" value would be earlier in memory).  In this
++ * case the caller's loop must terminate.  Checking against the
++ * end of the notes segment with a strict inequality is sufficient.
++ */
+ ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
+ 
+ /* (Only) checks that the image has the right magic number. */
+-- 
+1.7.2.5
+
diff --git a/xsa55-4.20016-libelf-abolish-obsolete-macros.patch b/xsa55-4.20017-libelf-abolish-obsolete-macros.patch
similarity index 87%
rename from xsa55-4.20016-libelf-abolish-obsolete-macros.patch
rename to xsa55-4.20017-libelf-abolish-obsolete-macros.patch
index dd7b9c9..4369599 100644
--- a/xsa55-4.20016-libelf-abolish-obsolete-macros.patch
+++ b/xsa55-4.20017-libelf-abolish-obsolete-macros.patch
@@ -1,7 +1,7 @@
-From fc5f528dd442e9c65dccd0c6f4bd8904f4ececac Mon Sep 17 00:00:00 2001
+From 3baaa4ffcd3e7dd6227f9bdf817f90e5b75aeda2 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
+Date: Fri, 14 Jun 2013 16:43:19 +0100
+Subject: [PATCH 17/23] 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.
@@ -23,10 +23,10 @@ v2: New patch.
  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
+index c5014d2..9fc4b94 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,
+@@ -116,9 +116,9 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
                                    struct elf_binary *elf, bool load)
  {
      struct elf_binary syms;
@@ -37,9 +37,9 @@ index 9bd3708..004ff51 100644
 +    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);
+     unsigned long *strtab_referenced = NULL;
+@@ -242,7 +242,7 @@ 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);
@@ -47,7 +47,7 @@ index 9bd3708..004ff51 100644
          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,
+@@ -278,7 +278,7 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
              if ( load )
              {
                  shdr2 = elf_shdr_by_index(elf, h);
@@ -57,7 +57,7 @@ index 9bd3708..004ff51 100644
                         size);
              }
 diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
-index 9be1594..4ff7085 100644
+index 2ca7732..5fa445e 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,
@@ -70,21 +70,21 @@ index 9be1594..4ff7085 100644
  	/* 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
+index 25a10d7..412ea70 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,
+@@ -220,8 +220,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_CONST_VOID end,
 +                               elf_ptrval start,
-+                               elf_ptrval end)
++                               elf_ptrval end,
+                                unsigned *total_note_count)
  {
      unsigned xen_elfnotes = 0;
-     ELF_HANDLE_DECL(elf_note) note;
-@@ -249,7 +249,7 @@ static unsigned elf_xen_parse_notes(struct elf_binary *elf,
+@@ -258,7 +258,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)
  {
@@ -94,7 +94,7 @@ index 8189fa5..21e82c9 100644
      unsigned len;
  
 diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
-index a6c97d0..6cf9622 100644
+index 06799af..e2e75af 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,
@@ -157,19 +157,19 @@ index a6c97d0..6cf9622 100644
      uint64_t i, count, paddr, offset, filesz, memsz;
 -    ELF_PTRVAL_VOID dest;
 +    elf_ptrval dest;
+     /*
+      * Let bizarre ELFs write the output image up to twice; this
+      * calculation is just to ensure our copying loop is no worse than
+@@ -334,7 +334,7 @@ elf_errorstatus elf_load_binary(struct elf_binary *elf)
+         remain_allow_copy -= memsz;
  
-     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)
+@@ -343,7 +343,7 @@ elf_errorstatus elf_load_binary(struct elf_binary *elf)
      return 0;
  }
  
@@ -179,10 +179,10 @@ index a6c97d0..6cf9622 100644
      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
+index 4a83133..e202249 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
+@@ -171,7 +171,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);
@@ -191,7 +191,7 @@ index eb89c31..27c9841 100644
  
      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
+@@ -185,7 +185,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);
@@ -200,7 +200,7 @@ index eb89c31..27c9841 100644
  
      if ( index >= count )
          return ELF_INVALID_HANDLE(elf_phdr);
-@@ -216,24 +216,24 @@ const char *elf_strfmt(struct elf_binary *elf, elf_ptrval start)
+@@ -233,24 +233,24 @@ const char *elf_strfmt(struct elf_binary *elf, elf_ptrval start)
      return str;
  }
  
@@ -229,7 +229,7 @@ index eb89c31..27c9841 100644
  {
      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
+@@ -258,8 +258,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)
  {
@@ -240,7 +240,7 @@ index eb89c31..27c9841 100644
      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
+@@ -283,7 +283,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)
  {
@@ -249,7 +249,7 @@ index eb89c31..27c9841 100644
      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
+@@ -295,7 +295,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));
  }
  
@@ -258,7 +258,7 @@ index eb89c31..27c9841 100644
  {
      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_
+@@ -304,7 +304,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)
  {
@@ -267,7 +267,7 @@ index eb89c31..27c9841 100644
      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
+@@ -322,7 +322,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)
  {
@@ -277,10 +277,10 @@ index eb89c31..27c9841 100644
  
      if ( descsz % unitsz || idx >= descsz / unitsz )
 diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
-index 4fc2496..b78d8a7 100644
+index f95fe88..174f8da 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,
+@@ -61,13 +61,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:
@@ -295,7 +295,7 @@ index 4fc2496..b78d8a7 100644
   *   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,
+@@ -76,8 +71,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.
@@ -304,7 +304,7 @@ index 4fc2496..b78d8a7 100644
   */
  
  typedef uintptr_t elf_ptrval;
-@@ -82,15 +75,9 @@ typedef uintptr_t elf_ptrval;
+@@ -85,15 +78,9 @@ typedef uintptr_t elf_ptrval;
  #define ELF_REALPTR2PTRVAL(realpointer) ((elf_ptrval)(realpointer))
    /* Converts an actual C pointer into a PTRVAL */
  
@@ -317,10 +317,10 @@ index 4fc2496..b78d8a7 100644
 -#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_PRPTRVAL "lu"
+   /*
+@@ -124,17 +111,6 @@ typedef uintptr_t elf_ptrval;
  #define ELF_HANDLE_PTRVAL(handleval)      ((handleval).ptrval)
    /* Converts a HANDLE to a PTRVAL. */
  
@@ -335,10 +335,10 @@ index 4fc2496..b78d8a7 100644
 -   * and no need for any casting.
 -   */
 -
- #define ELF_UNSAFE_PTR(ptrval) ((void*)(uintptr_t)(ptrval))
+ #define ELF_UNSAFE_PTR(ptrval) ((void*)(elf_ptrval)(ptrval))
    /*
     * Turns a PTRVAL into an actual C pointer.  Before this is done
-@@ -208,7 +184,7 @@ struct elf_binary {
+@@ -212,7 +188,7 @@ struct elf_binary {
      char data;
  
      ELF_HANDLE_DECL(elf_ehdr) ehdr;
@@ -347,7 +347,7 @@ index 4fc2496..b78d8a7 100644
      ELF_HANDLE_DECL(elf_shdr) sym_tab;
      uint64_t sym_strtab;
  
-@@ -286,7 +262,7 @@ struct elf_binary {
+@@ -290,7 +266,7 @@ struct elf_binary {
     * str should be a HANDLE.
     */
  
@@ -356,7 +356,7 @@ index 4fc2496..b78d8a7 100644
                               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
+@@ -342,17 +318,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 */
@@ -379,7 +379,7 @@ index 4fc2496..b78d8a7 100644
  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*,
+@@ -391,7 +367,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);
  
@@ -388,7 +388,7 @@ index 4fc2496..b78d8a7 100644
  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 {
+@@ -426,9 +402,9 @@ struct xen_elfnote {
  
  struct elf_dom_parms {
      /* raw */
diff --git a/xsa55-4.20018-libxc-Add-range-checking-to-xc_dom_binloader.patch b/xsa55-4.20018-libxc-Add-range-checking-to-xc_dom_binloader.patch
new file mode 100644
index 0000000..74774ec
--- /dev/null
+++ b/xsa55-4.20018-libxc-Add-range-checking-to-xc_dom_binloader.patch
@@ -0,0 +1,69 @@
+From b06e277b1fc08c7da3befeb3ac3950e1d941585d Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 14 Jun 2013 16:43:19 +0100
+Subject: [PATCH 18/23] libxc: Add range checking to xc_dom_binloader
+
+This is a simple binary image loader with its own metadata format.
+However, it is too careless with image-supplied values.
+
+Add the following checks:
+
+ * That the image is bigger than the metadata table; otherwise the
+   pointer arithmetic to calculate the metadata table location may
+   yield undefined and dangerous values.
+
+ * When clamping the end of the region to search, that we do not
+   calculate pointers beyond the end of the image.  The C
+   specification does not permit this and compilers are becoming ever
+   more determined to miscompile code when they can "prove" various
+   falsehoods based on assertions from the C spec.
+
+ * That the supplied image is big enough for the text we are allegedly
+   copying from it.  Otherwise we might have a read overrun and copy
+   the results (perhaps a lot of secret data) into the guest.
+
+This is part of the fix to a security issue, XSA-55.
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+---
+ tools/libxc/xc_dom_binloader.c |   15 +++++++++++++--
+ 1 files changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/tools/libxc/xc_dom_binloader.c b/tools/libxc/xc_dom_binloader.c
+index bde93f7..8596a28 100644
+--- a/tools/libxc/xc_dom_binloader.c
++++ b/tools/libxc/xc_dom_binloader.c
+@@ -123,10 +123,13 @@ static struct xen_bin_image_table *find_table(struct xc_dom_image *dom)
+     uint32_t *probe_ptr;
+     uint32_t *probe_end;
+ 
++    if ( dom->kernel_size < sizeof(*table) )
++        return NULL;
+     probe_ptr = dom->kernel_blob;
+-    probe_end = dom->kernel_blob + dom->kernel_size - sizeof(*table);
+-    if ( (void*)probe_end > (dom->kernel_blob + 8192) )
++    if ( dom->kernel_size > (8192 + sizeof(*table)) )
+         probe_end = dom->kernel_blob + 8192;
++    else
++        probe_end = dom->kernel_blob + dom->kernel_size - sizeof(*table);
+ 
+     for ( table = NULL; probe_ptr < probe_end; probe_ptr++ )
+     {
+@@ -282,6 +285,14 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
+         return -EINVAL;
+     }
+ 
++    if ( image_size < skip ||
++         image_size - skip < text_size )
++    {
++        DOMPRINTF("%s: image is too small for declared text size",
++                  __FUNCTION__);
++        return -EINVAL;
++    }
++
+     memcpy(dest, image + skip, text_size);
+     memset(dest + text_size, 0, bss_size);
+ 
+-- 
+1.7.2.5
+
diff --git a/xsa55-4.20019-libxc-check-failure-of-xc_dom_-_to_ptr-xc_map_foreig.patch b/xsa55-4.20019-libxc-check-failure-of-xc_dom_-_to_ptr-xc_map_foreig.patch
new file mode 100644
index 0000000..6107620
--- /dev/null
+++ b/xsa55-4.20019-libxc-check-failure-of-xc_dom_-_to_ptr-xc_map_foreig.patch
@@ -0,0 +1,382 @@
+From 77c0829fa751f052f7b8ec08287aef6e7ba97bc5 Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 14 Jun 2013 16:43:19 +0100
+Subject: [PATCH 19/23] libxc: check failure of xc_dom_*_to_ptr, xc_map_foreign_range
+
+The return values from xc_dom_*_to_ptr and xc_map_foreign_range are
+sometimes dereferenced, or subjected to pointer arithmetic, without
+checking whether the relevant function failed and returned NULL.
+
+Add an appropriate error check at every call site.
+
+Changes in the 4.2 backport of this series:
+* Fix tools/libxc/xc_dom_x86.c:setup_pgtables_x86_32.
+* Fix tools/libxc/xc_dom_ia64.c:start_info_ia64.
+* Fix tools/libxc/ia64/xc_ia64_dom_fwloader.c:xc_dom_load_fw_kernel.
+
+This is part of the fix to a security issue, XSA-55.
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+---
+ tools/libxc/ia64/xc_ia64_dom_fwloader.c |    2 +
+ tools/libxc/xc_dom_binloader.c          |    6 +++
+ tools/libxc/xc_dom_core.c               |    6 +++
+ tools/libxc/xc_dom_elfloader.c          |   13 +++++++
+ tools/libxc/xc_dom_ia64.c               |    6 +++
+ tools/libxc/xc_dom_x86.c                |   55 +++++++++++++++++++++++++++++++
+ tools/libxc/xc_domain_restore.c         |   27 +++++++++++++++
+ tools/libxc/xc_offline_page.c           |    5 +++
+ 8 files changed, 120 insertions(+), 0 deletions(-)
+
+diff --git a/tools/libxc/ia64/xc_ia64_dom_fwloader.c b/tools/libxc/ia64/xc_ia64_dom_fwloader.c
+index cdf3333..dbd3349 100644
+--- a/tools/libxc/ia64/xc_ia64_dom_fwloader.c
++++ b/tools/libxc/ia64/xc_ia64_dom_fwloader.c
+@@ -60,6 +60,8 @@ static int xc_dom_load_fw_kernel(struct xc_dom_image *dom)
+     unsigned long i;
+ 
+     dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart);
++    if ( dest == NULL )
++        return -1;
+     memcpy(dest, dom->kernel_blob, FW_SIZE);
+ 
+     /* Synchronize cache.  */
+diff --git a/tools/libxc/xc_dom_binloader.c b/tools/libxc/xc_dom_binloader.c
+index 8596a28..553b366 100644
+--- a/tools/libxc/xc_dom_binloader.c
++++ b/tools/libxc/xc_dom_binloader.c
+@@ -277,6 +277,12 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
+     DOMPRINTF("  bss_size:  0x%" PRIx32 "", bss_size);
+ 
+     dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart, &dest_size);
++    if ( dest == NULL )
++    {
++        DOMPRINTF("%s: xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart)"
++                  " => NULL", __FUNCTION__);
++        return -EINVAL;
++    }
+ 
+     if ( dest_size < text_size ||
+          dest_size - text_size < bss_size )
+diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
+index 8913e41..a54ddae 100644
+--- a/tools/libxc/xc_dom_core.c
++++ b/tools/libxc/xc_dom_core.c
+@@ -868,6 +868,12 @@ int xc_dom_build_image(struct xc_dom_image *dom)
+                                   ramdisklen) != 0 )
+             goto err;
+         ramdiskmap = xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg);
++        if ( ramdiskmap == NULL )
++        {
++            DOMPRINTF("%s: xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg) => NULL",
++                      __FUNCTION__);
++            goto err;
++        }
+         if ( unziplen )
+         {
+             if ( xc_dom_do_gunzip(dom->xch,
+diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
+index 9fc4b94..61b5798 100644
+--- a/tools/libxc/xc_dom_elfloader.c
++++ b/tools/libxc/xc_dom_elfloader.c
+@@ -139,6 +139,12 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
+             return 0;
+         size = dom->kernel_seg.vend - dom->bsd_symtab_start;
+         hdr_ptr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start, &allow_size);
++        if ( hdr_ptr == NULL )
++        {
++            DOMPRINTF("%s/load: xc_dom_vaddr_to_ptr(dom,dom->bsd_symtab_start"
++                      " => NULL", __FUNCTION__);
++            return -1;
++        }
+         elf->caller_xdest_base = hdr_ptr;
+         elf->caller_xdest_size = allow_size;
+         hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
+@@ -384,7 +390,14 @@ static elf_errorstatus xc_dom_load_elf_kernel(struct xc_dom_image *dom)
+     xen_pfn_t pages;
+ 
+     elf->dest_base = xc_dom_seg_to_ptr_pages(dom, &dom->kernel_seg, &pages);
++    if ( elf->dest_base == NULL )
++    {
++        DOMPRINTF("%s: xc_dom_vaddr_to_ptr(dom,dom->kernel_seg)"
++                  " => NULL", __FUNCTION__);
++        return -1;
++    }
+     elf->dest_size = pages * XC_DOM_PAGE_SIZE(dom);
++
+     rc = elf_load_binary(elf);
+     if ( rc < 0 )
+     {
+diff --git a/tools/libxc/xc_dom_ia64.c b/tools/libxc/xc_dom_ia64.c
+index dcd1523..7c0eff1 100644
+--- a/tools/libxc/xc_dom_ia64.c
++++ b/tools/libxc/xc_dom_ia64.c
+@@ -60,6 +60,12 @@ int start_info_ia64(struct xc_dom_image *dom)
+ 
+     DOMPRINTF_CALLED(dom->xch);
+ 
++    if ( start_info == NULL )
++    {
++        DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
++        return -1; /* our caller throws away our return value :-/ */
++    }
++
+     memset(start_info, 0, sizeof(*start_info));
+     sprintf(start_info->magic, dom->guest_type);
+     start_info->flags = dom->flags;
+diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c
+index 0cf1687..75d6b83 100644
+--- a/tools/libxc/xc_dom_x86.c
++++ b/tools/libxc/xc_dom_x86.c
+@@ -144,6 +144,9 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
+     xen_vaddr_t addr;
+     xen_pfn_t pgpfn;
+ 
++    if ( l2tab == NULL )
++        goto pfn_error;
++
+     for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
+           addr += PAGE_SIZE_X86 )
+     {
+@@ -151,6 +154,8 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
+         {
+             /* get L1 tab, make L2 entry */
+             l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
++            if ( l1tab == NULL )
++                goto pfn_error;
+             l2off = l2_table_offset_i386(addr);
+             l2tab[l2off] =
+                 pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
+@@ -169,6 +174,11 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
+             l1tab = NULL;
+     }
+     return 0;
++
++pfn_error:
++    xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
++                 "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
++    return -EINVAL;
+ }
+ 
+ /*
+@@ -219,6 +229,12 @@ static xen_pfn_t move_l3_below_4G(struct xc_dom_image *dom,
+         goto out;
+ 
+     l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
++    if ( l3tab == NULL )
++    {
++        DOMPRINTF("%s: xc_dom_pfn_to_ptr(dom, l3pfn, 1) => NULL",
++                  __FUNCTION__);
++        return l3mfn; /* our one call site will call xc_dom_panic and fail */
++    }
+     memset(l3tab, 0, XC_DOM_PAGE_SIZE(dom));
+ 
+     DOMPRINTF("%s: successfully relocated L3 below 4G. "
+@@ -262,6 +278,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
+     }
+ 
+     l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
++    if ( l3tab == NULL )
++        goto pfn_error;
+ 
+     for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
+           addr += PAGE_SIZE_X86 )
+@@ -270,6 +288,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
+         {
+             /* get L2 tab, make L3 entry */
+             l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1);
++            if ( l2tab == NULL )
++                goto pfn_error;
+             l3off = l3_table_offset_pae(addr);
+             l3tab[l3off] =
+                 pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
+@@ -280,6 +300,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
+         {
+             /* get L1 tab, make L2 entry */
+             l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
++            if ( l1tab == NULL )
++                goto pfn_error;
+             l2off = l2_table_offset_pae(addr);
+             l2tab[l2off] =
+                 pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
+@@ -306,6 +328,11 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
+         l3tab[3] = pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
+     }
+     return 0;
++
++pfn_error:
++    xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
++                 "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
++    return -EINVAL;
+ }
+ 
+ #undef L1_PROT
+@@ -344,6 +371,9 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
+     uint64_t addr;
+     xen_pfn_t pgpfn;
+ 
++    if ( l4tab == NULL )
++        goto pfn_error;
++
+     for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
+           addr += PAGE_SIZE_X86 )
+     {
+@@ -351,6 +381,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
+         {
+             /* get L3 tab, make L4 entry */
+             l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
++            if ( l3tab == NULL )
++                goto pfn_error;
+             l4off = l4_table_offset_x86_64(addr);
+             l4tab[l4off] =
+                 pfn_to_paddr(xc_dom_p2m_guest(dom, l3pfn)) | L4_PROT;
+@@ -361,6 +393,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
+         {
+             /* get L2 tab, make L3 entry */
+             l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1);
++            if ( l2tab == NULL )
++                goto pfn_error;
+             l3off = l3_table_offset_x86_64(addr);
+             l3tab[l3off] =
+                 pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
+@@ -373,6 +407,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
+         {
+             /* get L1 tab, make L2 entry */
+             l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
++            if ( l1tab == NULL )
++                goto pfn_error;
+             l2off = l2_table_offset_x86_64(addr);
+             l2tab[l2off] =
+                 pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
+@@ -393,6 +429,11 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
+             l1tab = NULL;
+     }
+     return 0;
++
++pfn_error:
++    xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
++                 "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
++    return -EINVAL;
+ }
+ 
+ #undef L1_PROT
+@@ -410,6 +451,8 @@ static int alloc_magic_pages(struct xc_dom_image *dom)
+     if ( xc_dom_alloc_segment(dom, &dom->p2m_seg, "phys2mach", 0, p2m_size) )
+         return -1;
+     dom->p2m_guest = xc_dom_seg_to_ptr(dom, &dom->p2m_seg);
++    if ( dom->p2m_guest == NULL )
++        return -1;
+ 
+     /* allocate special pages */
+     dom->start_info_pfn = xc_dom_alloc_page(dom, "start info");
+@@ -434,6 +477,12 @@ static int start_info_x86_32(struct xc_dom_image *dom)
+ 
+     DOMPRINTF_CALLED(dom->xch);
+ 
++    if ( start_info == NULL )
++    {
++        DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
++        return -1; /* our caller throws away our return value :-/ */
++    }
++
+     memset(start_info, 0, sizeof(*start_info));
+     strncpy(start_info->magic, dom->guest_type, sizeof(start_info->magic));
+     start_info->magic[sizeof(start_info->magic) - 1] = '\0';
+@@ -474,6 +523,12 @@ static int start_info_x86_64(struct xc_dom_image *dom)
+ 
+     DOMPRINTF_CALLED(dom->xch);
+ 
++    if ( start_info == NULL )
++    {
++        DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
++        return -1; /* our caller throws away our return value :-/ */
++    }
++
+     memset(start_info, 0, sizeof(*start_info));
+     strncpy(start_info->magic, dom->guest_type, sizeof(start_info->magic));
+     start_info->magic[sizeof(start_info->magic) - 1] = '\0';
+diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
+index b4c0b10..3994f8f 100644
+--- a/tools/libxc/xc_domain_restore.c
++++ b/tools/libxc/xc_domain_restore.c
+@@ -1556,6 +1556,12 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
+                     mfn = ctx->p2m[pfn];
+                     buf = xc_map_foreign_range(xch, dom, PAGE_SIZE,
+                                                PROT_READ | PROT_WRITE, mfn);
++                    if ( buf == NULL )
++                    {
++                        ERROR("xc_map_foreign_range for generation id"
++                              " buffer failed");
++                        goto out;
++                    }
+ 
+                     generationid = *(unsigned long long *)(buf + offset);
+                     *(unsigned long long *)(buf + offset) = generationid + 1;
+@@ -1713,6 +1719,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
+                 l3tab = (uint64_t *)
+                     xc_map_foreign_range(xch, dom, PAGE_SIZE,
+                                          PROT_READ, ctx->p2m[i]);
++                if ( l3tab == NULL )
++                {
++                    PERROR("xc_map_foreign_range failed (for l3tab)");
++                    goto out;
++                }
+ 
+                 for ( j = 0; j < 4; j++ )
+                     l3ptes[j] = l3tab[j];
+@@ -1739,6 +1750,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
+                 l3tab = (uint64_t *)
+                     xc_map_foreign_range(xch, dom, PAGE_SIZE,
+                                          PROT_READ | PROT_WRITE, ctx->p2m[i]);
++                if ( l3tab == NULL )
++                {
++                    PERROR("xc_map_foreign_range failed (for l3tab, 2nd)");
++                    goto out;
++                }
+ 
+                 for ( j = 0; j < 4; j++ )
+                     l3tab[j] = l3ptes[j];
+@@ -1909,6 +1925,12 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
+             SET_FIELD(ctxt, user_regs.edx, mfn);
+             start_info = xc_map_foreign_range(
+                 xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
++            if ( start_info == NULL )
++            {
++                PERROR("xc_map_foreign_range failed (for start_info)");
++                goto out;
++            }
++
+             SET_FIELD(start_info, nr_pages, dinfo->p2m_size);
+             SET_FIELD(start_info, shared_info, shared_info_frame<<PAGE_SHIFT);
+             SET_FIELD(start_info, flags, 0);
+@@ -2056,6 +2078,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
+     /* Restore contents of shared-info page. No checking needed. */
+     new_shared_info = xc_map_foreign_range(
+         xch, dom, PAGE_SIZE, PROT_WRITE, shared_info_frame);
++    if ( new_shared_info == NULL )
++    {
++        PERROR("xc_map_foreign_range failed (for new_shared_info)");
++        goto out;
++    }
+ 
+     /* restore saved vcpu_info and arch specific info */
+     MEMCPY_FIELD(new_shared_info, old_shared_info, vcpu_info);
+diff --git a/tools/libxc/xc_offline_page.c b/tools/libxc/xc_offline_page.c
+index 089a361..36b9812 100644
+--- a/tools/libxc/xc_offline_page.c
++++ b/tools/libxc/xc_offline_page.c
+@@ -714,6 +714,11 @@ int xc_exchange_page(xc_interface *xch, int domid, xen_pfn_t mfn)
+ 
+         new_p = xc_map_foreign_range(xch, domid, PAGE_SIZE,
+                                      PROT_READ|PROT_WRITE, new_mfn);
++        if ( new_p == NULL )
++        {
++            ERROR("failed to map new_p for copy, guest may be broken?");
++            goto failed;
++        }
+         memcpy(new_p, backup, PAGE_SIZE);
+         munmap(new_p, PAGE_SIZE);
+         mops.arg1.mfn = new_mfn;
+-- 
+1.7.2.5
+
diff --git a/xsa55-4.20020-libxc-check-return-values-from-malloc.patch b/xsa55-4.20020-libxc-check-return-values-from-malloc.patch
new file mode 100644
index 0000000..8060a39
--- /dev/null
+++ b/xsa55-4.20020-libxc-check-return-values-from-malloc.patch
@@ -0,0 +1,272 @@
+From 8dc90d163650ce8aa36ae0b46debab83cc61edb6 Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 14 Jun 2013 16:43:19 +0100
+Subject: [PATCH 20/23] libxc: check return values from malloc
+
+A sufficiently malformed input to libxc (such as a malformed input ELF
+or other guest-controlled data) might cause one of libxc's malloc() to
+fail.  In this case we need to make sure we don't dereference or do
+pointer arithmetic on the result.
+
+Search for all occurrences of \b(m|c|re)alloc in libxc, and all
+functions which call them, and add appropriate error checking where
+missing.
+
+This includes the functions xc_dom_malloc*, which now print a message
+when they fail so that callers don't have to do so.
+
+The function xc_cpuid_to_str wasn't provided with a sane return value
+and has a pretty strange API, which now becomes a little stranger.
+There are no in-tree callers.
+
+Changes in the Xen 4.2 version of this series:
+* No need to fix code relating to ARM.
+* No need to fix code relating to superpage support.
+* Additionally fix `dom->p2m_host = xc_dom_malloc...' in xc_dom_ia64.c.
+
+This is part of the fix to a security issue, XSA-55.
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+---
+ tools/libxc/xc_cpuid_x86.c      |   20 ++++++++++++++++++--
+ tools/libxc/xc_dom_core.c       |   13 +++++++++++++
+ tools/libxc/xc_dom_elfloader.c  |    2 ++
+ tools/libxc/xc_dom_ia64.c       |    6 ++++++
+ tools/libxc/xc_dom_x86.c        |    3 +++
+ tools/libxc/xc_domain_restore.c |    5 +++++
+ tools/libxc/xc_linux_osdep.c    |    4 ++++
+ tools/libxc/xc_private.c        |    2 ++
+ tools/libxc/xenctrl.h           |    2 +-
+ 9 files changed, 54 insertions(+), 3 deletions(-)
+
+diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c
+index 0882ce6..da435ce 100644
+--- a/tools/libxc/xc_cpuid_x86.c
++++ b/tools/libxc/xc_cpuid_x86.c
+@@ -589,6 +589,8 @@ static int xc_cpuid_do_domctl(
+ static char *alloc_str(void)
+ {
+     char *s = malloc(33);
++    if ( s == NULL )
++        return s;
+     memset(s, 0, 33);
+     return s;
+ }
+@@ -600,6 +602,8 @@ void xc_cpuid_to_str(const unsigned int *regs, char **strs)
+     for ( i = 0; i < 4; i++ )
+     {
+         strs[i] = alloc_str();
++        if ( strs[i] == NULL )
++            continue;
+         for ( j = 0; j < 32; j++ )
+             strs[i][j] = !!((regs[i] & (1U << (31 - j)))) ? '1' : '0';
+     }
+@@ -680,7 +684,7 @@ int xc_cpuid_check(
+     const char **config,
+     char **config_transformed)
+ {
+-    int i, j;
++    int i, j, rc;
+     unsigned int regs[4];
+ 
+     memset(config_transformed, 0, 4 * sizeof(*config_transformed));
+@@ -692,6 +696,11 @@ int xc_cpuid_check(
+         if ( config[i] == NULL )
+             continue;
+         config_transformed[i] = alloc_str();
++        if ( config_transformed[i] == NULL )
++        {
++            rc = -ENOMEM;
++            goto fail_rc;
++        }
+         for ( j = 0; j < 32; j++ )
+         {
+             unsigned char val = !!((regs[i] & (1U << (31 - j))));
+@@ -708,12 +717,14 @@ int xc_cpuid_check(
+     return 0;
+ 
+  fail:
++    rc = -EPERM;
++ fail_rc:
+     for ( i = 0; i < 4; i++ )
+     {
+         free(config_transformed[i]);
+         config_transformed[i] = NULL;
+     }
+-    return -EPERM;
++    return rc;
+ }
+ 
+ /*
+@@ -758,6 +769,11 @@ int xc_cpuid_set(
+         }
+         
+         config_transformed[i] = alloc_str();
++        if ( config_transformed[i] == NULL )
++        {
++            rc = -ENOMEM;
++            goto fail;
++        }
+ 
+         for ( j = 0; j < 32; j++ )
+         {
+diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
+index a54ddae..3cbf9f7 100644
+--- a/tools/libxc/xc_dom_core.c
++++ b/tools/libxc/xc_dom_core.c
+@@ -120,9 +120,17 @@ void *xc_dom_malloc(struct xc_dom_image *dom, size_t size)
+ {
+     struct xc_dom_mem *block;
+ 
++    if ( size > SIZE_MAX - sizeof(*block) )
++    {
++        DOMPRINTF("%s: unreasonable allocation size", __FUNCTION__);
++        return NULL;
++    }
+     block = malloc(sizeof(*block) + size);
+     if ( block == NULL )
++    {
++        DOMPRINTF("%s: allocation failed", __FUNCTION__);
+         return NULL;
++    }
+     memset(block, 0, sizeof(*block) + size);
+     block->next = dom->memblocks;
+     dom->memblocks = block;
+@@ -138,7 +146,10 @@ void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size)
+ 
+     block = malloc(sizeof(*block));
+     if ( block == NULL )
++    {
++        DOMPRINTF("%s: allocation failed", __FUNCTION__);
+         return NULL;
++    }
+     memset(block, 0, sizeof(*block));
+     block->mmap_len = size;
+     block->mmap_ptr = mmap(NULL, block->mmap_len,
+@@ -146,6 +157,7 @@ void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size)
+                            -1, 0);
+     if ( block->mmap_ptr == MAP_FAILED )
+     {
++        DOMPRINTF("%s: mmap failed", __FUNCTION__);
+         free(block);
+         return NULL;
+     }
+@@ -202,6 +214,7 @@ void *xc_dom_malloc_filemap(struct xc_dom_image *dom,
+         close(fd);
+     if ( block != NULL )
+         free(block);
++    DOMPRINTF("%s: failed (on file `%s')", __FUNCTION__, filename);
+     return NULL;
+ }
+ 
+diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
+index 61b5798..be58276 100644
+--- a/tools/libxc/xc_dom_elfloader.c
++++ b/tools/libxc/xc_dom_elfloader.c
+@@ -329,6 +329,8 @@ static elf_errorstatus xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
+         return rc;
+ 
+     elf = xc_dom_malloc(dom, sizeof(*elf));
++    if ( elf == NULL )
++        return -1;
+     dom->private_loader = elf;
+     rc = elf_init(elf, dom->kernel_blob, dom->kernel_size);
+     xc_elf_set_logfile(dom->xch, elf, 1);
+diff --git a/tools/libxc/xc_dom_ia64.c b/tools/libxc/xc_dom_ia64.c
+index 7c0eff1..076821c 100644
+--- a/tools/libxc/xc_dom_ia64.c
++++ b/tools/libxc/xc_dom_ia64.c
+@@ -188,6 +188,12 @@ int arch_setup_meminit(struct xc_dom_image *dom)
+ 
+     /* setup initial p2m */
+     dom->p2m_host = xc_dom_malloc(dom, sizeof(xen_pfn_t) * nbr);
++    if ( dom->p2m_host == NULL )
++    {
++        DOMPRINTF("%s: xc_dom_malloc failed for p2m_host",
++                  __FUNCTION__);
++        return -1;
++    }
+     for ( pfn = 0; pfn < nbr; pfn++ )
+         dom->p2m_host[pfn] = start + pfn;
+ 
+diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c
+index 75d6b83..448d9a1 100644
+--- a/tools/libxc/xc_dom_x86.c
++++ b/tools/libxc/xc_dom_x86.c
+@@ -780,6 +780,9 @@ int arch_setup_meminit(struct xc_dom_image *dom)
+     }
+ 
+     dom->p2m_host = xc_dom_malloc(dom, sizeof(xen_pfn_t) * dom->total_pages);
++    if ( dom->p2m_host == NULL )
++        return -EINVAL;
++
+     if ( dom->superpages )
+     {
+         int count = dom->total_pages >> SUPERPAGE_PFN_SHIFT;
+diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
+index 3994f8f..f9ed6b2 100644
+--- a/tools/libxc/xc_domain_restore.c
++++ b/tools/libxc/xc_domain_restore.c
+@@ -1180,6 +1180,11 @@ static int apply_batch(xc_interface *xch, uint32_t dom, struct restore_ctx *ctx,
+ 
+     /* Map relevant mfns */
+     pfn_err = calloc(j, sizeof(*pfn_err));
++    if ( pfn_err == NULL )
++    {
++        PERROR("allocation for pfn_err failed");
++        return -1;
++    }
+     region_base = xc_map_foreign_bulk(
+         xch, dom, PROT_WRITE, region_mfn, pfn_err, j);
+ 
+diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c
+index 787e742..98e041c 100644
+--- a/tools/libxc/xc_linux_osdep.c
++++ b/tools/libxc/xc_linux_osdep.c
+@@ -378,6 +378,8 @@ static void *linux_privcmd_map_foreign_range(xc_interface *xch, xc_osdep_handle
+ 
+     num = (size + XC_PAGE_SIZE - 1) >> XC_PAGE_SHIFT;
+     arr = calloc(num, sizeof(xen_pfn_t));
++    if ( arr == NULL )
++        return NULL;
+ 
+     for ( i = 0; i < num; i++ )
+         arr[i] = mfn + i;
+@@ -402,6 +404,8 @@ static void *linux_privcmd_map_foreign_ranges(xc_interface *xch, xc_osdep_handle
+     num_per_entry = chunksize >> XC_PAGE_SHIFT;
+     num = num_per_entry * nentries;
+     arr = calloc(num, sizeof(xen_pfn_t));
++    if ( arr == NULL )
++        return NULL;
+ 
+     for ( i = 0; i < nentries; i++ )
+         for ( j = 0; j < num_per_entry; j++ )
+diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c
+index 3e03a91..848ceed 100644
+--- a/tools/libxc/xc_private.c
++++ b/tools/libxc/xc_private.c
+@@ -771,6 +771,8 @@ const char *xc_strerror(xc_interface *xch, int errcode)
+         errbuf = pthread_getspecific(errbuf_pkey);
+         if (errbuf == NULL) {
+             errbuf = malloc(XS_BUFSIZE);
++            if ( errbuf == NULL )
++                return "(failed to allocate errbuf)";
+             pthread_setspecific(errbuf_pkey, errbuf);
+         }
+ 
+diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
+index b7741ca..8952048 100644
+--- a/tools/libxc/xenctrl.h
++++ b/tools/libxc/xenctrl.h
+@@ -1778,7 +1778,7 @@ int xc_cpuid_set(xc_interface *xch,
+ int xc_cpuid_apply_policy(xc_interface *xch,
+                           domid_t domid);
+ void xc_cpuid_to_str(const unsigned int *regs,
+-                     char **strs);
++                     char **strs); /* some strs[] may be NULL if ENOMEM */
+ int xc_mca_op(xc_interface *xch, struct xen_mc *mc);
+ #endif
+ 
+-- 
+1.7.2.5
+
diff --git a/xsa55-4.20021-libxc-range-checks-in-xc_dom_p2m_host-and-_guest.patch b/xsa55-4.20021-libxc-range-checks-in-xc_dom_p2m_host-and-_guest.patch
new file mode 100644
index 0000000..0baf7f5
--- /dev/null
+++ b/xsa55-4.20021-libxc-range-checks-in-xc_dom_p2m_host-and-_guest.patch
@@ -0,0 +1,47 @@
+From 052a689aa526ca51fd70528d4b0f83dfb2de99c1 Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 14 Jun 2013 16:43:19 +0100
+Subject: [PATCH 21/23] libxc: range checks in xc_dom_p2m_host and _guest
+
+These functions take guest pfns and look them up in the p2m.  They did
+no range checking.
+
+However, some callers, notably xc_dom_boot.c:setup_hypercall_page want
+to pass untrusted guest-supplied value(s).  It is most convenient to
+detect this here and return INVALID_MFN.
+
+This is part of the fix to a security issue, XSA-55.
+
+Changes from Xen 4.2 version of this patch:
+* 4.2 lacks dom->rambase_pfn, so don't add/subtract/check it.
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+---
+ tools/libxc/xc_dom.h |    4 ++++
+ 1 files changed, 4 insertions(+), 0 deletions(-)
+
+diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h
+index 0161459..d801f66 100644
+--- a/tools/libxc/xc_dom.h
++++ b/tools/libxc/xc_dom.h
+@@ -331,6 +331,8 @@ static inline xen_pfn_t xc_dom_p2m_host(struct xc_dom_image *dom, xen_pfn_t pfn)
+ {
+     if (dom->shadow_enabled)
+         return pfn;
++    if (pfn >= dom->total_pages)
++        return INVALID_MFN;
+     return dom->p2m_host[pfn];
+ }
+ 
+@@ -339,6 +341,8 @@ static inline xen_pfn_t xc_dom_p2m_guest(struct xc_dom_image *dom,
+ {
+     if (xc_dom_feature_translated(dom))
+         return pfn;
++    if (pfn >= dom->total_pages)
++        return INVALID_MFN;
+     return dom->p2m_host[pfn];
+ }
+ 
+-- 
+1.7.2.5
+
diff --git a/xsa55-4.20022-libxc-check-blob-size-before-proceeding-in-xc_dom_ch.patch b/xsa55-4.20022-libxc-check-blob-size-before-proceeding-in-xc_dom_ch.patch
new file mode 100644
index 0000000..fba1f4d
--- /dev/null
+++ b/xsa55-4.20022-libxc-check-blob-size-before-proceeding-in-xc_dom_ch.patch
@@ -0,0 +1,31 @@
+From 2a548e22915535ac13694eb38222903bca7245e3 Mon Sep 17 00:00:00 2001
+From: Matthew Daley <mattjd at gmail.com>
+Date: Fri, 14 Jun 2013 16:43:19 +0100
+Subject: [PATCH 22/23] libxc: check blob size before proceeding in xc_dom_check_gzip
+
+This is part of the fix to a security issue, XSA-55.
+
+Signed-off-by: Matthew Daley <mattjd at gmail.com>
+---
+ tools/libxc/xc_dom_core.c |    5 +++++
+ 1 files changed, 5 insertions(+), 0 deletions(-)
+
+diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
+index 3cbf9f7..f8d1b08 100644
+--- a/tools/libxc/xc_dom_core.c
++++ b/tools/libxc/xc_dom_core.c
+@@ -284,6 +284,11 @@ size_t xc_dom_check_gzip(xc_interface *xch, void *blob, size_t ziplen)
+     unsigned char *gzlen;
+     size_t unziplen;
+ 
++    if ( ziplen < 6 )
++        /* Too small.  We need (i.e. the subsequent code relies on)
++         * 2 bytes for the magic number plus 4 bytes length. */
++        return 0;
++
+     if ( strncmp(blob, "\037\213", 2) )
+         /* not gzipped */
+         return 0;
+-- 
+1.7.2.5
+
diff --git a/xsa55-4.20023-libxc-Better-range-check-in-xc_dom_alloc_segment.patch b/xsa55-4.20023-libxc-Better-range-check-in-xc_dom_alloc_segment.patch
new file mode 100644
index 0000000..896e4f3
--- /dev/null
+++ b/xsa55-4.20023-libxc-Better-range-check-in-xc_dom_alloc_segment.patch
@@ -0,0 +1,33 @@
+From d21d36e84354c04638b60a739a5f7c3d9f8adaf8 Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson at eu.citrix.com>
+Date: Fri, 14 Jun 2013 16:43:19 +0100
+Subject: [PATCH 23/23] libxc: Better range check in xc_dom_alloc_segment
+
+If seg->pfn is too large, the arithmetic in the range check might
+overflow, defeating the range check.
+
+This is part of the fix to a security issue, XSA-55.
+
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3 at citrix.com>
+---
+ tools/libxc/xc_dom_core.c |    3 ++-
+ 1 files changed, 2 insertions(+), 1 deletions(-)
+
+diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
+index f8d1b08..e79e38d 100644
+--- a/tools/libxc/xc_dom_core.c
++++ b/tools/libxc/xc_dom_core.c
+@@ -509,7 +509,8 @@ int xc_dom_alloc_segment(struct xc_dom_image *dom,
+     seg->vstart = start;
+     seg->pfn = (seg->vstart - dom->parms.virt_base) / page_size;
+ 
+-    if ( pages > dom->total_pages || /* double test avoids overflow probs */
++    if ( pages > dom->total_pages || /* multiple test avoids overflow probs */
++         seg->pfn > dom->total_pages ||
+          pages > dom->total_pages - seg->pfn)
+     {
+         xc_dom_panic(dom->xch, XC_OUT_OF_MEMORY,
+-- 
+1.7.2.5
+


More information about the scm-commits mailing list