diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c index 4d7b8e0a4d..2e695599b1 100644 --- a/tools/libxc/xc_dom_elfloader.c +++ b/tools/libxc/xc_dom_elfloader.c @@ -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; diff --git a/tools/libxc/xc_hvm_build.c b/tools/libxc/xc_hvm_build.c index 9831bab192..1fa5658702 100644 --- a/tools/libxc/xc_hvm_build.c +++ b/tools/libxc/xc_hvm_build.c @@ -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; diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c index 1b3818fc7f..b3c5d4cc72 100644 --- a/xen/arch/x86/domain_build.c +++ b/xen/arch/x86/domain_build.c @@ -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 ) diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c index 1ccf7d35a6..ab58b8b86a 100644 --- a/xen/common/libelf/libelf-loader.c +++ b/xen/common/libelf/libelf-loader.c @@ -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 + 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) diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h index 9de84eb267..d77bda6f5d 100644 --- a/xen/include/xen/libelf.h +++ b/xen/include/xen/libelf.h @@ -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);