[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