libelf-loader: introduce elf_load_image
authorStefano Stabellini <stefano.stabellini@eu.citrix.com>
Mon, 23 Jan 2012 09:42:12 +0000 (09:42 +0000)
committerStefano Stabellini <stefano.stabellini@eu.citrix.com>
Mon, 23 Jan 2012 09:42:12 +0000 (09:42 +0000)
Implement a new function, called elf_load_image, to perform the
actually copy of the elf image and clearing the padding.  The function
is implemented as memcpy and memset when the library is built as part
of the tools, but it is implemented as raw_copy_to_guest and
raw_clear_guest when built as part of Xen, so that it can be safely
called with an HVM style dom0.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
Committed-by: Keir Fraser <keir@xen.org>
tools/libxc/xc_dom_elfloader.c
tools/libxc/xc_hvm_build.c
xen/arch/x86/domain_build.c
xen/common/libelf/libelf-loader.c
xen/include/xen/libelf.h

index 4d7b8e0a4dacd4b2ff7d6358fb990b8216e26a5b..2e695599b1961a0828fd4c3da7f3f13cd51faefd 100644 (file)
@@ -310,9 +310,15 @@ static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
 static int xc_dom_load_elf_kernel(struct xc_dom_image *dom)
 {
     struct elf_binary *elf = dom->private_loader;
+    int rc;
 
     elf->dest = xc_dom_seg_to_ptr(dom, &dom->kernel_seg);
-    elf_load_binary(elf);
+    rc = elf_load_binary(elf);
+    if ( rc < 0 )
+    {
+        DOMPRINTF("%s: failed to load elf binary", __FUNCTION__);
+        return rc;
+    }
     if ( dom->parms.bsd_symtab )
         xc_dom_load_elf_symtab(dom, elf, 1);
     return 0;
index 9831bab19262aa00cdd9a1587bae79bc85583f61..1fa5658702949d33dfbaac1aa810d3730d5ce9bd 100644 (file)
@@ -109,8 +109,9 @@ static int loadelfimage(
     elf->dest += elf->pstart & (PAGE_SIZE - 1);
 
     /* Load the initial elf image. */
-    elf_load_binary(elf);
-    rc = 0;
+    rc = elf_load_binary(elf);
+    if ( rc < 0 )
+        PERROR("Failed to load elf binary\n");
 
     munmap(elf->dest, pages << PAGE_SHIFT);
     elf->dest = NULL;
index 1b3818fc7fb2fbb0651cc882c7dbd97964843c04..b3c5d4cc72c7a3c4643a53b522e8e4423995bec2 100644 (file)
@@ -903,7 +903,12 @@ int __init construct_dom0(
 
     /* Copy the OS image and free temporary buffer. */
     elf.dest = (void*)vkern_start;
-    elf_load_binary(&elf);
+    rc = elf_load_binary(&elf);
+    if ( rc < 0 )
+    {
+        printk("Failed to load the kernel binary\n");
+        return rc;
+    }
     bootstrap_map(NULL);
 
     if ( UNSET_ADDR != parms.virt_hypercall )
index 1ccf7d35a68aacf05a7df60835bca42e1295026d..ab58b8b86ad3dbbc48fbe1008e4a7dfb2cfd5a50 100644 (file)
@@ -107,11 +107,34 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
     elf->log_caller_data = log_caller_data;
     elf->verbose = verbose;
 }
+
+static int elf_load_image(void *dst, const void *src, uint64_t filesz, uint64_t memsz)
+{
+    memcpy(dst, src, filesz);
+    memset(dst + filesz, 0, memsz - filesz);
+    return 0;
+}
 #else
+#include <asm/guest_access.h>
+
 void elf_set_verbose(struct elf_binary *elf)
 {
     elf->verbose = 1;
 }
+
+static int elf_load_image(void *dst, const void *src, uint64_t filesz, uint64_t memsz)
+{
+    int rc;
+    if ( filesz > ULONG_MAX || memsz > ULONG_MAX )
+        return -1;
+    rc = raw_copy_to_guest(dst, src, filesz);
+    if ( rc != 0 )
+        return -1;
+    rc = raw_clear_guest(dst + filesz, memsz - filesz);
+    if ( rc != 0 )
+        return -1;
+    return 0;
+}
 #endif
 
 /* Calculate the required additional kernel space for the elf image */
@@ -237,7 +260,7 @@ void elf_parse_binary(struct elf_binary *elf)
             __FUNCTION__, elf->pstart, elf->pend);
 }
 
-void elf_load_binary(struct elf_binary *elf)
+int elf_load_binary(struct elf_binary *elf)
 {
     const elf_phdr *phdr;
     uint64_t i, count, paddr, offset, filesz, memsz;
@@ -256,11 +279,12 @@ void elf_load_binary(struct elf_binary *elf)
         dest = elf_get_ptr(elf, paddr);
         elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%p -> 0x%p\n",
                 __func__, i, dest, dest + filesz);
-        memcpy(dest, elf->image + offset, filesz);
-        memset(dest + filesz, 0, memsz - filesz);
+        if ( elf_load_image(dest, elf->image + offset, filesz, memsz) != 0 )
+            return -1;
     }
 
     elf_load_bsdsyms(elf);
+    return 0;
 }
 
 void *elf_get_ptr(struct elf_binary *elf, unsigned long addr)
index 9de84eb26787b0daf2340137a940581b320232b1..d77bda6f5d381dd9f03dd1d0ef87387067559703 100644 (file)
@@ -198,7 +198,7 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback*,
 #endif
 
 void elf_parse_binary(struct elf_binary *elf);
-void elf_load_binary(struct elf_binary *elf);
+int elf_load_binary(struct elf_binary *elf);
 
 void *elf_get_ptr(struct elf_binary *elf, unsigned long addr);
 uint64_t elf_lookup_addr(struct elf_binary *elf, const char *symbol);