All Virtuozzo development lists (kernel + QEMU)
 help / color / mirror / Atom feed
* [Devel] [PATCH RHEL10 COMMIT] dm-qcow2: fix NULL deref in merge_backward complete without an active merge
       [not found] <20260706110002.1024515-22-khorenko@virtuozzo.com>
@ 2026-08-05 20:20 ` Konstantin Khorenko
  0 siblings, 0 replies; only message in thread
From: Konstantin Khorenko @ 2026-08-05 20:20 UTC (permalink / raw)


The commit is pushed to "branch-rh10-6.12.0-211.39.1.16.x.vz10-ovz" and will appear at git at bitbucket.org:openvz/vzkernel.git
after rh10-6.12.0-211.39.1.16.2.vz10
------>
commit 0b0514cc0ada5c48fe5d239f54c3ba803d4fa4a1
Author: Konstantin Khorenko <khorenko@virtuozzo.com>
Date:   Mon Jul 6 12:59:59 2026 +0200

    dm-qcow2: fix NULL deref in merge_backward complete without an active merge
    
    qcow2_merge_backward_complete() loaded *tgt->backward_merge.pqcow2 in its
    variable initializer, before checking the merge state:
    
            struct qcow2 *qcow2 = *tgt->backward_merge.pqcow2, *i;
            ...
            if (tgt->backward_merge.state != BACKWARD_MERGE_WAIT_COMPLETION)
                    return -EBUSY;
    
    tgt->backward_merge.pqcow2 stays NULL until a "merge_backward start" message
    sets it, so a `dmsetup message <dev> 0 "merge_backward complete"` on a device
    that never started a backward merge dereferences NULL in the kernel and
    crashes the host (NULL-ptr deref at qcow2_merge_backward_complete+0x19,
    offset backward_merge(632)+pqcow2(72) = 0x2c0).
    Any unprivileged-of-the-VE holder of the dm control device can trigger it.
    
    Move the pqcow2 load below the state check. When the state really is
    BACKWARD_MERGE_WAIT_COMPLETION, pqcow2 was set by "start" under the same
    ctl_mutex and is never cleared while in that state, so the normal
    start->...->complete path is unchanged; the no-active-merge case now returns
    -EBUSY (the driver's existing "wrong merge state" convention) instead of
    oopsing. The sibling verbs (cancel/update_eventfd/progress) already guard
    their pqcow2 use behind the state and are not affected.
    
    Fixes: 11ba92733c99a ("dm-qcow2: allow specifying depth to merge intermediate images")
    Feature: dm-qcow2: block device over QCOW2 files driver
    https://virtuozzo.atlassian.net/browse/VSTOR-137234
    Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
    Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
---
 drivers/md/dm-qcow2-cmd.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/md/dm-qcow2-cmd.c b/drivers/md/dm-qcow2-cmd.c
index c15c46a0fe8b7..e1a94bc4a140c 100644
--- a/drivers/md/dm-qcow2-cmd.c
+++ b/drivers/md/dm-qcow2-cmd.c
@@ -366,14 +366,19 @@ void qcow2_merge_backward_work(struct work_struct *work)
 
 static int qcow2_merge_backward_complete(struct qcow2_target *tgt)
 {
-	struct qcow2 *qcow2 = *tgt->backward_merge.pqcow2, *i;
+	struct qcow2 *qcow2, *i;
 	int ret;
 
 	lockdep_assert_held(&tgt->ctl_mutex);
 
+	/*
+	 * .pqcow2 is NULL until the first "merge_backward start" and
+	 * is valid while the state is BACKWARD_MERGE_WAIT_COMPLETION.
+	 */
 	if (tgt->backward_merge.state != BACKWARD_MERGE_WAIT_COMPLETION)
 		return -EBUSY;
 
+	qcow2 = *tgt->backward_merge.pqcow2;
 	*tgt->backward_merge.pqcow2 = qcow2->lower;
 
 	i = tgt->top;

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-08-05 20:20 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20260706110002.1024515-22-khorenko@virtuozzo.com>
2026-08-05 20:20 ` [Devel] [PATCH RHEL10 COMMIT] dm-qcow2: fix NULL deref in merge_backward complete without an active merge Konstantin Khorenko

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.