]> xenbits.xensource.com Git - people/dariof/xen.git/commitdiff
libxc: don't fail domain creation when unpacking initrd fails
authorJan Beulich <jbeulich@suse.com>
Tue, 6 Feb 2018 16:29:33 +0000 (17:29 +0100)
committerJan Beulich <jbeulich@suse.com>
Tue, 6 Feb 2018 16:29:33 +0000 (17:29 +0100)
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 <jbeulich@suse.com>
Acked-by: Wei Liu <wei.liu2@citrix.com>
tools/libxc/include/xc_dom.h
tools/libxc/xc_dom_core.c

index 08be8a8f3f3570cfef7f9d41bff4b058619f1324..491cad8114cbe96f0a0dd9adc43904de17ae5877 100644 (file)
@@ -298,7 +298,6 @@ int xc_dom_mem_init(struct xc_dom_image *dom, unsigned int mem_mb);
 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);
index 3e65aff22ba28c7e22ca6bba2fdbb161edd26479..96e71dd2d9c3d7e676dc548904cb42c93bfc83cf 100644 (file)
@@ -314,22 +314,6 @@ int xc_dom_kernel_check_size(struct xc_dom_image *dom, size_t sz)
     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_dom_image *dom, unsigned int mod)
     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_dom_image *dom, unsigned int mod)
     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;