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

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