All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH for-5.2 v2] qcow2: Fix corruption on write_zeroes with MAY_UNMAP
@ 2020-11-24  9:28 Kevin Wolf
  2020-11-24 10:09 ` Alberto Garcia
  0 siblings, 1 reply; 2+ messages in thread
From: Kevin Wolf @ 2020-11-24  9:28 UTC (permalink / raw)
  To: qemu-block
  Cc: kwolf, vsementsov, berto, zhang_youjia, qemu-devel, mlevitsk,
	andrey.shinkevich, mreitz

From: Maxim Levitsky <mlevitsk@redhat.com>

Commit 205fa50750 ("qcow2: Add subcluster support to zero_in_l2_slice()")
introduced a subtle change to code in zero_in_l2_slice:

It swapped the order of

1. qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
2. set_l2_entry(s, l2_slice, l2_index + i, QCOW_OFLAG_ZERO);
3. qcow2_free_any_clusters(bs, old_offset, 1, QCOW2_DISCARD_REQUEST);

To

1. qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
2. qcow2_free_any_clusters(bs, old_offset, 1, QCOW2_DISCARD_REQUEST);
3. set_l2_entry(s, l2_slice, l2_index + i, QCOW_OFLAG_ZERO);

It seems harmless, however the call to qcow2_free_any_clusters can
trigger a cache flush which can mark the L2 table as clean, and
assuming that this was the last write to it, a stale version of it
will remain on the disk.

Now we have a valid L2 entry pointing to a freed cluster. Oops.

Fixes: 205fa50750 ("qcow2: Add subcluster support to zero_in_l2_slice()")
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
[ kwolf: Fixed to restore the correct original order from before
  205fa50750; added comments like in discard_in_l2_slice(). ]
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/qcow2-cluster.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 485b4cb92e..bd0597842f 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -2010,14 +2010,17 @@ static int zero_in_l2_slice(BlockDriverState *bs, uint64_t offset,
             continue;
         }
 
+        /* First update L2 entries */
         qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
-        if (unmap) {
-            qcow2_free_any_cluster(bs, old_l2_entry, QCOW2_DISCARD_REQUEST);
-        }
         set_l2_entry(s, l2_slice, l2_index + i, new_l2_entry);
         if (has_subclusters(s)) {
             set_l2_bitmap(s, l2_slice, l2_index + i, new_l2_bitmap);
         }
+
+        /* Then decrease the refcount */
+        if (unmap) {
+            qcow2_free_any_cluster(bs, old_l2_entry, QCOW2_DISCARD_REQUEST);
+        }
     }
 
     qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
-- 
2.28.0



^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH for-5.2 v2] qcow2: Fix corruption on write_zeroes with MAY_UNMAP
  2020-11-24  9:28 [PATCH for-5.2 v2] qcow2: Fix corruption on write_zeroes with MAY_UNMAP Kevin Wolf
@ 2020-11-24 10:09 ` Alberto Garcia
  0 siblings, 0 replies; 2+ messages in thread
From: Alberto Garcia @ 2020-11-24 10:09 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block
  Cc: kwolf, vsementsov, zhang_youjia, qemu-devel, mreitz,
	andrey.shinkevich, mlevitsk

On Tue 24 Nov 2020 10:28:15 AM CET, Kevin Wolf wrote:
> From: Maxim Levitsky <mlevitsk@redhat.com>
>
> Commit 205fa50750 ("qcow2: Add subcluster support to zero_in_l2_slice()")
> introduced a subtle change to code in zero_in_l2_slice:
>
> It swapped the order of
>
> 1. qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
> 2. set_l2_entry(s, l2_slice, l2_index + i, QCOW_OFLAG_ZERO);
> 3. qcow2_free_any_clusters(bs, old_offset, 1, QCOW2_DISCARD_REQUEST);
>
> To
>
> 1. qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
> 2. qcow2_free_any_clusters(bs, old_offset, 1, QCOW2_DISCARD_REQUEST);
> 3. set_l2_entry(s, l2_slice, l2_index + i, QCOW_OFLAG_ZERO);
>
> It seems harmless, however the call to qcow2_free_any_clusters can
> trigger a cache flush which can mark the L2 table as clean, and
> assuming that this was the last write to it, a stale version of it
> will remain on the disk.
>
> Now we have a valid L2 entry pointing to a freed cluster. Oops.
>
> Fixes: 205fa50750 ("qcow2: Add subcluster support to zero_in_l2_slice()")
> Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
> [ kwolf: Fixed to restore the correct original order from before
>   205fa50750; added comments like in discard_in_l2_slice(). ]

Reviewed-by: Alberto Garcia <berto@igalia.com>

Berto


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2020-11-24 10:12 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-24  9:28 [PATCH for-5.2 v2] qcow2: Fix corruption on write_zeroes with MAY_UNMAP Kevin Wolf
2020-11-24 10:09 ` Alberto Garcia

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.