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

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