Blob Blame History Raw
From cedf819b7ab7e5621eae9395302566fb701db7d1 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Fri, 24 May 2013 17:52:42 +0100
Subject: [PATCH 10/14] libelf: Make all callers call elf_check_broken

This arranges that if the new pointer reference error checking
tripped, we actually get a message about it.  In this patch these
messages do not change the actual return values from the various
functions: so pointer reference errors do not prevent loading.  This
is for fear that some existing kernels might cause the code to make
these wild references, which would then break, which is not a good
thing in a security patch.

In xen/arch/x86/domain_build.c we have to introduce an "out" label and
change all of the "return rc" beyond the relevant point into "goto
out".

Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>

v3.1:
    Add error check to xc_dom_parse_elf_kernel.
    Move check in xc_hvm_build_x86.c:setup_guest to right place.

v2 Acked-by: Ian Campbell <ian.campbell@citrix.com>
v2 Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

v2: Style fixes.
---
 tools/libxc/xc_dom_elfloader.c |   22 +++++++++++++++++++---
 tools/libxc/xc_hvm_build.c     |    5 +++++
 tools/xcutils/readnotes.c      |    3 +++
 xen/arch/x86/domain_build.c    |   23 ++++++++++++++++++-----
 4 files changed, 45 insertions(+), 8 deletions(-)

diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
index 0096a8f..5fe9a6b 100644
--- a/tools/libxc/xc_dom_elfloader.c
+++ b/tools/libxc/xc_dom_elfloader.c
@@ -277,6 +277,13 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
             elf_store_field(elf, shdr, e32.sh_name, 0);
     }
 
+    if ( elf_check_broken(&syms) )
+        DOMPRINTF("%s: symbols ELF broken: %s", __FUNCTION__,
+                  elf_check_broken(&syms));
+    if ( elf_check_broken(elf) )
+        DOMPRINTF("%s: ELF broken: %s", __FUNCTION__,
+                  elf_check_broken(elf));
+
     if ( tables == 0 )
     {
         DOMPRINTF("%s: no symbol table present", __FUNCTION__);
@@ -313,13 +320,16 @@ static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
     {
         xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: ELF image"
                      " has no shstrtab", __FUNCTION__);
-        return -EINVAL;
+        rc = -EINVAL;
+        goto out;
     }
 
     /* parse binary and get xen meta info */
     elf_parse_binary(elf);
     if ( (rc = elf_xen_parse(elf, &dom->parms)) != 0 )
-        return rc;
+    {
+        goto out;
+    }
 
     /* find kernel segment */
     dom->kernel_seg.vstart = dom->parms.virt_kstart;
@@ -332,7 +342,13 @@ static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
     DOMPRINTF("%s: %s: 0x%" PRIx64 " -> 0x%" PRIx64 "",
               __FUNCTION__, dom->guest_type,
               dom->kernel_seg.vstart, dom->kernel_seg.vend);
-    return 0;
+    rc = 0;
+out:
+    if ( elf_check_broken(elf) )
+        DOMPRINTF("%s: ELF broken: %s", __FUNCTION__,
+                  elf_check_broken(elf));
+    
+    return rc;
 }
 
 static int xc_dom_load_elf_kernel(struct xc_dom_image *dom)
diff --git a/tools/libxc/xc_hvm_build.c b/tools/libxc/xc_hvm_build.c
index e3efca9..6c4e41e 100644
--- a/tools/libxc/xc_hvm_build.c
+++ b/tools/libxc/xc_hvm_build.c
@@ -393,11 +393,16 @@ static int setup_guest(xc_interface *xch,
         munmap(page0, PAGE_SIZE);
     }
 
+    if ( elf_check_broken(&elf) )
+        ERROR("HVM ELF broken: %s", elf_check_broken(&elf));
+
     free(page_array);
     return 0;
 
  error_out:
     free(page_array);
+    if ( elf_check_broken(&elf) )
+        ERROR("HVM ELF broken, failing: %s", elf_check_broken(&elf));
     return -1;
 }
 
diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
index 9710d58..1e14aa0 100644
--- a/tools/xcutils/readnotes.c
+++ b/tools/xcutils/readnotes.c
@@ -223,6 +223,9 @@ int main(int argc, char **argv)
 		printf("__xen_guest: %s\n",
                        elf_strfmt(&elf, elf_section_start(&elf, shdr)));
 
+        if (elf_check_broken(&elf))
+		printf("warning: broken ELF: %s\n", elf_check_broken(&elf));
+
 	return 0;
 }
 
diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c
index 6467c36..49bb6a5 100644
--- a/xen/arch/x86/domain_build.c
+++ b/xen/arch/x86/domain_build.c
@@ -374,7 +374,7 @@ int __init construct_dom0(
 #endif
     elf_parse_binary(&elf);
     if ( (rc = elf_xen_parse(&elf, &parms)) != 0 )
-        return rc;
+        goto out;
 
     /* compatibility check */
     compatible = 0;
@@ -413,7 +413,8 @@ int __init construct_dom0(
     if ( !compatible )
     {
         printk("Mismatch between Xen and DOM0 kernel\n");
-        return -EINVAL;
+        rc = -EINVAL;
+        goto out;
     }
 
 #if defined(__x86_64__)
@@ -727,7 +728,8 @@ int __init construct_dom0(
          (v_end > HYPERVISOR_COMPAT_VIRT_START(d)) )
     {
         printk("DOM0 image overlaps with Xen private area.\n");
-        return -EINVAL;
+        rc = -EINVAL;
+        goto out;
     }
 
     if ( is_pv_32on64_domain(d) )
@@ -907,7 +909,8 @@ int __init construct_dom0(
         {
             write_ptbase(current);
             printk("Invalid HYPERCALL_PAGE field in ELF notes.\n");
-            return -1;
+            rc = -1;
+            goto out;
         }
         hypercall_page_initialise(
             d, (void *)(unsigned long)parms.virt_hypercall);
@@ -1254,9 +1257,19 @@ int __init construct_dom0(
 
     BUG_ON(rc != 0);
 
-    iommu_dom0_init(dom0);
+    if ( elf_check_broken(&elf) )
+        printk(" Xen warning: dom0 kernel broken ELF: %s\n",
+               elf_check_broken(&elf));
 
+    iommu_dom0_init(dom0);
     return 0;
+
+out:
+    if ( elf_check_broken(&elf) )
+        printk(" Xen dom0 kernel broken ELF: %s\n",
+               elf_check_broken(&elf));
+
+    return rc;
 }
 
 /*
-- 
1.7.2.5