Commit eb6009b092 ("cache, cow: Reduce use of bounce-buffer") first
introduced in nbdkit 1.14 added an optimization of the
read-modify-write mechanism used for unaligned heads and tails when
zeroing in the cache layer.
Unfortunately the part applied to the tail contained a mistake: It
zeroes the end of the buffer rather than the beginning. This causes
data corruption when you use the zero or trim function with an offset
and count which is not aligned to the block size.
We can demonstrate this by filling a buffer with data (100000 bytes in
the example), and then trimming that data which ought to zero it all
out but does not.
Before this commit:
$ nbdkit --filter=cow data "33 * 100000" --run 'nbdsh -u $uri -c
"h.trim(100000, 0)" ; nbdcopy $uri - | hexdump -C'
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00018000 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 |!!!!!!!!!!!!!!!!|
*
000186a0
After this commit:
$ ./nbdkit --filter=cow data "33 * 100000" --run 'nbdsh -u $uri -c
"h.trim(100000, 0)" ; nbdcopy $uri - | hexdump -C'
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000186a0
Fixes: commit eb6009b092ae642ed25f133d487dd40ef7bf70f8
Thanks: Ming Xie for originally finding the bug
---
filters/cache/cache.c | 2 +-
filters/cow/cow.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/filters/cache/cache.c b/filters/cache/cache.c
index f7b01039..c912c5fb 100644
--- a/filters/cache/cache.c
+++ b/filters/cache/cache.c
@@ -572,7 +572,7 @@ cache_zero (nbdkit_next *next,
ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&lock);
r = blk_read (next, blknum, block, err);
if (r != -1) {
- memset (&block[count], 0, blksize - count);
+ memset (block, 0, count);
r = blk_write (next, blknum, block, flags, err);
}
if (r == -1)
diff --git a/filters/cow/cow.c b/filters/cow/cow.c
index 74fcd61c..6ad42eec 100644
--- a/filters/cow/cow.c
+++ b/filters/cow/cow.c
@@ -449,7 +449,7 @@ cow_zero (nbdkit_next *next,
ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&rmw_lock);
r = blk_read (next, blknum, block, cow_on_read (), err);
if (r != -1) {
- memset (&block[count], 0, BLKSIZE - count);
+ memset (block, 0, count);
r = blk_write (blknum, block, err);
}
if (r == -1)
@@ -520,7 +520,7 @@ cow_trim (nbdkit_next *next,
ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&rmw_lock);
r = blk_read (next, blknum, block, cow_on_read (), err);
if (r != -1) {
- memset (&block[count], 0, BLKSIZE - count);
+ memset (block, 0, count);
r = blk_write (blknum, block, err);
}
if (r == -1)
--
2.32.0