Blame SOURCES/0001-cache-cow-Fix-data-corruption-in-zero-and-trim-on-un.patch

827db5
From 99788909d9ec36e3210cf85976fe5b18da690ddd Mon Sep 17 00:00:00 2001
827db5
From: "Richard W.M. Jones" <rjones@redhat.com>
827db5
Date: Wed, 4 Aug 2021 20:24:59 +0100
827db5
Subject: [PATCH] cache, cow: Fix data corruption in zero and trim on unaligned
827db5
 tail
827db5
827db5
Commit eb6009b092 ("cache, cow: Reduce use of bounce-buffer") first
827db5
introduced in nbdkit 1.14 added an optimization of the
827db5
read-modify-write mechanism used for unaligned heads and tails when
827db5
zeroing in the cache layer.
827db5
827db5
Unfortunately the part applied to the tail contained a mistake: It
827db5
zeroes the end of the buffer rather than the beginning.  This causes
827db5
data corruption when you use the zero or trim function with an offset
827db5
and count which is not aligned to the block size.
827db5
827db5
Although the bug has been around for years, a recent change made it
827db5
more likely to happen.  Commit c1905b0a28 ("cache, cow: Use a 64K
827db5
block size by default") increased the default block size from 4K to
827db5
64K.  Most filesystems use a 4K block size so operations like fstrim
827db5
will make 4K-aligned requests, and with a 4K block size also in the
827db5
cache or cow filter the unaligned case would never have been hit
827db5
before.
827db5
827db5
We can demonstrate the bug simply by filling a buffer with data
827db5
(100000 bytes in the example), and then trimming that data, which
827db5
ought to zero it out.
827db5
827db5
Before this commit there is data visible after the trim:
827db5
827db5
$ nbdkit --filter=cow data "0x21 * 100000" --run 'nbdsh -u $uri -c "h.trim(100000, 0)" ; nbdcopy $uri - | hexdump -C'
827db5
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
827db5
*
827db5
00018000  21 21 21 21 21 21 21 21  21 21 21 21 21 21 21 21  |!!!!!!!!!!!!!!!!|
827db5
*
827db5
000186a0
827db5
827db5
After this commit the trim completely clears the data:
827db5
827db5
$ nbdkit --filter=cow data "0x21 * 100000" --run 'nbdsh -u $uri -c "h.trim(100000, 0)" ; nbdcopy $uri - | hexdump -C'
827db5
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
827db5
*
827db5
000186a0
827db5
827db5
Thanks: Ming Xie for finding the bug
827db5
Fixes: commit eb6009b092ae642ed25f133d487dd40ef7bf70f8
827db5
(cherry picked from commit a0ae7b2158598ce48ac31706319007f716d01c87)
827db5
(cherry picked from commit c0b15574647672cb5c48178333acdd07424692ef)
827db5
---
827db5
 filters/cache/cache.c | 2 +-
827db5
 filters/cow/cow.c     | 2 +-
827db5
 2 files changed, 2 insertions(+), 2 deletions(-)
827db5
827db5
diff --git a/filters/cache/cache.c b/filters/cache/cache.c
827db5
index 91dcc43d..0616cc7b 100644
827db5
--- a/filters/cache/cache.c
827db5
+++ b/filters/cache/cache.c
827db5
@@ -493,7 +493,7 @@ cache_zero (struct nbdkit_next_ops *next_ops, void *nxdata,
827db5
     ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&lock);
827db5
     r = blk_read (next_ops, nxdata, blknum, block, err);
827db5
     if (r != -1) {
827db5
-      memset (&block[count], 0, blksize - count);
827db5
+      memset (block, 0, count);
827db5
       r = blk_write (next_ops, nxdata, blknum, block, flags, err);
827db5
     }
827db5
     if (r == -1)
827db5
diff --git a/filters/cow/cow.c b/filters/cow/cow.c
827db5
index 51ca64a4..1cfcc4e7 100644
827db5
--- a/filters/cow/cow.c
827db5
+++ b/filters/cow/cow.c
827db5
@@ -419,7 +419,7 @@ cow_zero (struct nbdkit_next_ops *next_ops, void *nxdata,
827db5
     ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&lock);
827db5
     r = blk_read (next_ops, nxdata, blknum, block, err);
827db5
     if (r != -1) {
827db5
-      memset (&block[count], 0, BLKSIZE - count);
827db5
+      memset (block, 0, count);
827db5
       r = blk_write (blknum, block, err);
827db5
     }
827db5
     if (r == -1)
827db5
-- 
fcc3c9
2.31.1
827db5