cache, cow: Fix data corruption in zero and trim on unaligned tail
Commit eb6009b0 ("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. Although the bug has been around for years, a recent change made it more likely to happen. Commit c1905b0a ("cache, cow: Use a 64K block size by default") increased the default block size from 4K to 64K. Most filesystems use a 4K block size so operations like fstrim will make 4K-aligned requests, and with a 4K block size also in the cache or cow filter the unaligned case would never have been hit before. We can demonstrate the bug simply by filling a buffer with data (100000 bytes in the example), and then trimming that data, which ought to zero it out. Before this commit there is data visible after the trim: $ nbdkit --filter=cow data "0x21 * 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 the trim completely clears the data: $ nbdkit --filter=cow data "0x21 * 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 Thanks: Ming Xie for finding the bug Fixes: commit eb6009b0 (cherry picked from commit a0ae7b21)
parent
fcf57509