diff -ur xen-3.4.2.orig//tools/libxc/xc_dom_bzimageloader.c xen-3.4.2//tools/libxc/xc_dom_bzimageloader.c --- tools/libxc/xc_dom_bzimageloader.c 2009-11-10 23:12:56.000000000 +0800 +++ tools/libxc/xc_dom_bzimageloader.c 2011-10-09 20:10:08.972815311 +0800 @@ -308,19 +308,19 @@ extern struct xc_dom_loader elf_loader; -static unsigned int payload_offset(struct setup_header *hdr) +static int check_magic(struct xc_dom_image *dom, const void *magic, size_t len) { - unsigned int off; + if (len > dom->kernel_size) + return 0; + + return (memcmp(dom->kernel_blob, magic, len) == 0); + } - off = (hdr->setup_sects + 1) * 512; - off += hdr->payload_offset; - return off; -} - -static int xc_dom_probe_bzimage_kernel(struct xc_dom_image *dom) +static int check_bzimage_kernel(struct xc_dom_image *dom, int verbose) { struct setup_header *hdr; - int ret; + uint64_t payload_offset, payload_length; + /* int ret; */ if ( dom->kernel_blob == NULL ) { @@ -352,20 +352,47 @@ return -EINVAL; } - dom->kernel_blob = dom->kernel_blob + payload_offset(hdr); - dom->kernel_size = hdr->payload_length; + /* upcast to 64 bits to avoid overflow */ + /* setup_sects is u8 and so cannot overflow */ + payload_offset = (hdr->setup_sects + 1) * 512; + payload_offset += hdr->payload_offset; + payload_length = hdr->payload_length; - if ( memcmp(dom->kernel_blob, "\037\213", 2) == 0 ) - { +/* if ( memcmp(dom->kernel_blob, "\037\213", 2) == 0 ) + { ret = xc_dom_try_gunzip(dom, &dom->kernel_blob, &dom->kernel_size); - if ( ret == -1 ) + if ( ret == -1 ) */ + if ( payload_offset >= dom->kernel_size ) + { + xc_dom_panic(XC_INVALID_KERNEL, "%s: payload offset overflow", + __FUNCTION__); + return -EINVAL; + } + if ( (payload_offset + payload_length) > dom->kernel_size ) + { + xc_dom_panic(XC_INVALID_KERNEL, "%s: payload length overflow", + __FUNCTION__); + } + + dom->kernel_blob = dom->kernel_blob + payload_offset; + dom->kernel_size = payload_length; + + if ( check_magic(dom, "\037\213", 2) ) + { + if ( xc_dom_try_gunzip(dom, &dom->kernel_blob, &dom->kernel_size) == -1 ) { - xc_dom_panic(XC_INVALID_KERNEL, - "%s: unable to gzip decompress kernel\n", - __FUNCTION__); + if ( verbose ) + xc_dom_panic(XC_INVALID_KERNEL, "%s: unable to decompress kernel\$n", + __FUNCTION__); return -EINVAL; } } + else + { + xc_dom_panic(XC_INVALID_KERNEL, "%s: unknown compression format\n", + __FUNCTION__); + return -EINVAL; + } else if ( memcmp(dom->kernel_blob, "\102\132\150", 3) == 0 ) { ret = xc_try_bzip2_decode(dom, &dom->kernel_blob, &dom->kernel_size);