At least Linux kernels have been able to work with gzip-ed initrd for quite some time; initrd compressed with other methods aren't even being attempted to unpack. Furthermore the unzip-ing routine used here isn't capable of dealing with various forms of concatenated files, each of which was gzip-ed separately (it is this particular case which has been the source of observed VM creation failures).
Hence, if unpacking fails, simply hand the compressed blob to the guest as is. Signed-off-by: Jan Beulich <jbeul...@suse.com> --- v3: Re-base. Add missing blank. v2: Almost full re-work, hopefully better meeting Ian's taste. --- a/tools/libxc/include/xc_dom.h +++ b/tools/libxc/include/xc_dom.h @@ -298,7 +298,6 @@ int xc_dom_mem_init(struct xc_dom_image int xc_dom_kernel_check_size(struct xc_dom_image *dom, size_t sz); int xc_dom_kernel_max_size(struct xc_dom_image *dom, size_t sz); -int xc_dom_module_check_size(struct xc_dom_image *dom, size_t sz); int xc_dom_module_max_size(struct xc_dom_image *dom, size_t sz); int xc_dom_devicetree_max_size(struct xc_dom_image *dom, size_t sz); --- a/tools/libxc/xc_dom_core.c +++ b/tools/libxc/xc_dom_core.c @@ -314,22 +314,6 @@ int xc_dom_kernel_check_size(struct xc_d return 0; } -int xc_dom_module_check_size(struct xc_dom_image *dom, size_t sz) -{ - /* No limit */ - if ( !dom->max_module_size ) - return 0; - - if ( sz > dom->max_module_size ) - { - xc_dom_panic(dom->xch, XC_INVALID_KERNEL, - "module image too large"); - return 1; - } - - return 0; -} - /* ------------------------------------------------------------------------ */ /* read files, copy memory blocks, with transparent gunzip */ @@ -1026,16 +1010,28 @@ static int xc_dom_build_module(struct xc char name[10]; if ( !dom->modules[mod].seg.vstart ) - { unziplen = xc_dom_check_gzip(dom->xch, dom->modules[mod].blob, dom->modules[mod].size); - if ( xc_dom_module_check_size(dom, unziplen) != 0 ) - unziplen = 0; - } else unziplen = 0; - modulelen = unziplen ? unziplen : dom->modules[mod].size; + modulelen = max(unziplen, dom->modules[mod].size); + if ( dom->max_module_size ) + { + if ( unziplen && modulelen > dom->max_module_size ) + { + modulelen = min(unziplen, dom->modules[mod].size); + if ( unziplen > modulelen ) + unziplen = 0; + } + if ( modulelen > dom->max_module_size ) + { + xc_dom_panic(dom->xch, XC_INVALID_KERNEL, + "module %u image too large", mod); + goto err; + } + } + snprintf(name, sizeof(name), "module%u", mod); if ( xc_dom_alloc_segment(dom, &dom->modules[mod].seg, name, dom->modules[mod].seg.vstart, modulelen) != 0 ) @@ -1050,11 +1046,18 @@ static int xc_dom_build_module(struct xc if ( unziplen ) { if ( xc_dom_do_gunzip(dom->xch, dom->modules[mod].blob, dom->modules[mod].size, - modulemap, modulelen) == -1 ) + modulemap, unziplen) != -1 ) + return 0; + if ( dom->modules[mod].size > modulelen ) goto err; } - else - memcpy(modulemap, dom->modules[mod].blob, dom->modules[mod].size); + + /* Fall back to handing over the raw blob. */ + memcpy(modulemap, dom->modules[mod].blob, dom->modules[mod].size); + /* If an unzip attempt was made, the buffer may no longer be all zero. */ + if ( unziplen > dom->modules[mod].size ) + memset(modulemap + dom->modules[mod].size, 0, + unziplen - dom->modules[mod].size); return 0; _______________________________________________ Xen-devel mailing list Xen-devel@lists.xenproject.org https://lists.xenproject.org/mailman/listinfo/xen-devel