# HG changeset patch # Parent 11931301845c3b4b6a358f2d7246874b1d10c05f diff -r 11931301845c tools/libxc/xc_dom_bzimageloader.c --- a/tools/libxc/xc_dom_bzimageloader.c Mon Mar 14 16:59:49 2011 +0000 +++ b/tools/libxc/xc_dom_bzimageloader.c Tue May 03 10:09:28 2011 +0100 @@ -61,18 +61,18 @@ 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; - off = (hdr->setup_sects + 1) * 512; - off += hdr->payload_offset; - return off; + return (memcmp(dom->kernel_blob, magic, len) == 0); } static int check_bzimage_kernel(struct xc_dom_image *dom, int verbose) { struct setup_header *hdr; + uint64_t payload_offset, payload_length; if ( dom->kernel_blob == NULL ) { @@ -107,14 +107,43 @@ return -EINVAL; } - dom->kernel_blob = dom->kernel_blob + payload_offset(hdr); - dom->kernel_size = hdr->payload_length; - if ( xc_dom_try_gunzip(dom, &dom->kernel_blob, &dom->kernel_size) == -1 ) + /* 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 ( payload_offset >= dom->kernel_size ) { - if ( verbose ) - xc_dom_panic(XC_INVALID_KERNEL, "%s: unable to decompress kernel\n", - __FUNCTION__); + 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__); + return -EINVAL; + } + + 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 ) + { + 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; }