Richard W.M. Jones
2021-Jul-24 13:06 UTC
[Libguestfs] [PATCH nbdkit] cow: Fix assert failure in cow_extents
$ 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
Eric Blake
2021-Jul-26 13:59 UTC
[Libguestfs] [PATCH nbdkit] cow: Fix assert failure in cow_extents
On Sat, Jul 24, 2021 at 02:06:16PM +0100, Richard W.M. Jones wrote:> $ 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(-)Ack. -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org