[Libguestfs] [PATCH nbdkit] cow: Fix assert failure in cow_extents

Richard W.M. Jones rjones at redhat.com
Sat Jul 24 13:06:16 UTC 2021


$ nbdkit sparse-random 4G --filter=cow --run 'nbdinfo --map $uri'
nbdkit: cow.c:591: cow_extents: Assertion `count > 0' failed.

This is caused because nbdinfo calls us with count = 0xfffffe00 which
is rounded up to the next boundary and overflows (so count = 0).

Use a 64 bit variable for count to allow rounding up.
---
 tests/Makefile.am               |  2 ++
 filters/cow/cow.c               | 16 +++++++++---
 tests/test-cow-extents-large.sh | 46 +++++++++++++++++++++++++++++++++
 3 files changed, 61 insertions(+), 3 deletions(-)

diff --git a/tests/Makefile.am b/tests/Makefile.am
index ba42f112..8e0304d4 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1404,6 +1404,7 @@ TESTS += \
 	test-cow.sh \
 	test-cow-extents1.sh \
 	test-cow-extents2.sh \
+	test-cow-extents-large.sh \
 	test-cow-unaligned.sh \
 	$(NULL)
 endif
@@ -1412,6 +1413,7 @@ EXTRA_DIST += \
 	test-cow.sh \
 	test-cow-extents1.sh \
 	test-cow-extents2.sh \
+	test-cow-extents-large.sh \
 	test-cow-null.sh \
 	test-cow-unaligned.sh \
 	$(NULL)
diff --git a/filters/cow/cow.c b/filters/cow/cow.c
index 83844845..3bd09399 100644
--- a/filters/cow/cow.c
+++ b/filters/cow/cow.c
@@ -571,19 +571,23 @@ cow_cache (nbdkit_next *next,
 /* Extents. */
 static int
 cow_extents (nbdkit_next *next,
-             void *handle, uint32_t count, uint64_t offset, uint32_t flags,
+             void *handle, uint32_t count32, uint64_t offset, uint32_t flags,
              struct nbdkit_extents *extents, int *err)
 {
   const bool can_extents = next->can_extents (next);
   const bool req_one = flags & NBDKIT_FLAG_REQ_ONE;
+  uint64_t count = count32;
   uint64_t end;
   uint64_t blknum;
 
-  /* To make this easier, align the requested extents to whole blocks. */
+  /* To make this easier, align the requested extents to whole blocks.
+   * Note that count is a 64 bit variable containing at most a 32 bit
+   * value so rounding up is safe here.
+   */
   end = offset + count;
   offset = ROUND_DOWN (offset, BLKSIZE);
   end = ROUND_UP (end, BLKSIZE);
-  count  = end - offset;
+  count = end - offset;
   blknum = offset / BLKSIZE;
 
   assert (IS_ALIGNED (offset, BLKSIZE));
@@ -628,6 +632,12 @@ cow_extents (nbdkit_next *next,
        * as we can.
        */
       for (;;) {
+        /* nbdkit_extents_full cannot read more than a 32 bit range
+         * (range_count), but count is a 64 bit quantity, so don't
+         * overflow range_count here.
+         */
+        if (range_count >= UINT32_MAX - BLKSIZE + 1) break;
+
         blknum++;
         offset += BLKSIZE;
         count -= BLKSIZE;
diff --git a/tests/test-cow-extents-large.sh b/tests/test-cow-extents-large.sh
new file mode 100755
index 00000000..ea981dcb
--- /dev/null
+++ b/tests/test-cow-extents-large.sh
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+# nbdkit
+# Copyright (C) 2018-2021 Red Hat Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of Red Hat nor the names of its contributors may be
+# used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+# Regression test of an earlier overflow in cow_extents.
+# https://listman.redhat.com/archives/libguestfs/2021-July/msg00037.html
+
+source ./functions.sh
+set -e
+set -x
+
+requires_filter cow
+requires_plugin sparse-random
+requires nbdinfo --version
+
+for size in 0 3G 4G 5G 8G; do
+    nbdkit -U - sparse-random $size --filter=cow --run 'nbdinfo --map $uri'
+done
-- 
2.32.0




More information about the Libguestfs mailing list