All Virtuozzo development lists (kernel + QEMU)
 help / color / mirror / Atom feed
From: Alexander Ivanov <alexander.ivanov@virtuozzo.com>
To: den@openvz.org
Cc: devel@openvz.org
Subject: [Devel] [PATCH hci-8.1 v4 09/11] dm-ploop: fix use-after-free on the last inflight_md decrement
Date: Mon, 12 Oct 2026 15:26:44 +0200	[thread overview]
Message-ID: <20261012132646.41494-10-alexander.ivanov@virtuozzo.com> (raw)
In-Reply-To: <20261012132646.41494-1-alexander.ivanov@virtuozzo.com>

The last piwb reference is often dropped from the BAT write completion
in aio context. ploop_bat_write_finish() completes the data pios there,
and once the last original request is done, suspend can finish and a
table reload or remove can free the ploop in ploop_destroy(). The
completing CPU still decrements inflight_md, calls wake_up() on
inflight_md_wq and frees the piwb into ploop->pio_pool, so it can lock
a freed waitqueue or free into a destroyed mempool.

Nothing on the suspend or destroy path waits for inflight_md, and the
one waiter that exists, ploop_suspend_submitting_pios(), checks the
counter without a lock. It can see zero and return before wake_up() and
ploop_free_piwb() are done with the ploop, so the message can finish
and the table can be destroyed under the waker.

Free the piwb first, then decrement inflight_md and wake the waiters
under inflight_md_wq.lock as the last access to the ploop. Have the
waiters check the counter under the same lock, so they cannot see zero
until the waker has released it, and wait for it in ploop_destroy()
before freeing anything.

https://virtuozzo.atlassian.net/browse/VSTOR-148171
Feature: dm-ploop: ploop target driver

Signed-off-by: Alexander Ivanov <alexander.ivanov@virtuozzo.com>
---
 drivers/md/dm-ploop-cmd.c    |  6 ++++--
 drivers/md/dm-ploop-map.c    | 22 ++++++++++++++++++----
 drivers/md/dm-ploop-target.c |  7 +++++++
 3 files changed, 29 insertions(+), 6 deletions(-)

diff --git a/drivers/md/dm-ploop-cmd.c b/drivers/md/dm-ploop-cmd.c
index ab17520c2d56..977b6920a5b4 100644
--- a/drivers/md/dm-ploop-cmd.c
+++ b/drivers/md/dm-ploop-cmd.c
@@ -154,8 +154,10 @@ static int ploop_suspend_submitting_pios(struct ploop *ploop)
 	if (ret)
 		goto out;
 
-	ret = wait_event_interruptible(ploop->inflight_md_wq,
-				       !atomic_read(&ploop->inflight_md));
+	spin_lock_irq(&ploop->inflight_md_wq.lock);
+	ret = wait_event_interruptible_locked_irq(ploop->inflight_md_wq,
+					!atomic_read(&ploop->inflight_md));
+	spin_unlock_irq(&ploop->inflight_md_wq.lock);
 out:
 	if (ret)
 		ploop_resume_submitting_pios(ploop);
diff --git a/drivers/md/dm-ploop-map.c b/drivers/md/dm-ploop-map.c
index c313f303fff9..f673e94d0e38 100644
--- a/drivers/md/dm-ploop-map.c
+++ b/drivers/md/dm-ploop-map.c
@@ -909,9 +909,25 @@ static void ploop_free_piwb(struct ploop_index_wb *piwb)
 
 static void ploop_bat_write_finish(struct pio *pio, void *piwb_ptr,
 				     blk_status_t bi_status);
+/*
+ * Waiters check inflight_md under inflight_md_wq.lock, so they cannot see
+ * zero while we still hold it. Once it is zero, the ploop may be freed, so
+ * this must be the last access to it.
+ */
+static void ploop_dec_inflight_md(struct ploop *ploop)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ploop->inflight_md_wq.lock, flags);
+	if (atomic_dec_and_test(&ploop->inflight_md))
+		wake_up_locked(&ploop->inflight_md_wq);
+	spin_unlock_irqrestore(&ploop->inflight_md_wq.lock, flags);
+}
+
 static void ploop_put_piwb(struct ploop_index_wb *piwb)
 {
 	if (atomic_dec_and_test(&piwb->count)) {
+		struct ploop *ploop = piwb->ploop;
 
 		ploop_bat_write_finish(piwb->pio, piwb, piwb->bi_status);
 
@@ -925,9 +941,8 @@ static void ploop_put_piwb(struct ploop_index_wb *piwb)
 		 * zero keeps it as is
 		 */
 
-		if (atomic_dec_and_test(&piwb->ploop->inflight_md))
-			wake_up(&piwb->ploop->inflight_md_wq);
 		ploop_free_piwb(piwb);
+		ploop_dec_inflight_md(ploop);
 	}
 }
 
@@ -1105,9 +1120,8 @@ void ploop_break_bat_update(struct ploop *ploop, struct md_page *md,
 	spin_unlock(&md->md_lock);
 	spin_unlock_irqrestore(&ploop->bat_lock, flags);
 
-	if (atomic_dec_and_test(&ploop->inflight_md))
-		wake_up(&ploop->inflight_md_wq);
 	ploop_free_piwb(piwb);
+	ploop_dec_inflight_md(ploop);
 }
 
 static void ploop_bat_page_zero_cluster(struct ploop *ploop,
diff --git a/drivers/md/dm-ploop-target.c b/drivers/md/dm-ploop-target.c
index 3b589579741c..11d25277d60c 100644
--- a/drivers/md/dm-ploop-target.c
+++ b/drivers/md/dm-ploop-target.c
@@ -192,6 +192,13 @@ static void ploop_destroy(struct ploop *ploop)
 		if (ploop->kt_allocator)
 			kthread_stop(ploop->kt_allocator->task);
 
+		/* BAT writes may still be completing from aio context */
+		spin_lock_irq(&ploop->inflight_md_wq.lock);
+		wait_event_lock_irq(ploop->inflight_md_wq,
+				    !atomic_read(&ploop->inflight_md),
+				    ploop->inflight_md_wq.lock);
+		spin_unlock_irq(&ploop->inflight_md_wq.lock);
+
 		WARN_ON(!llist_empty(&ploop->pios[PLOOP_LIST_PREPARE]));
 		WARN_ON(!llist_empty(&ploop->llresubmit_pios));
 		WARN_ON(!llist_empty(&ploop->enospc_pios));
-- 
2.53.0

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

  parent reply	other threads:[~2026-10-12 13:28 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-12 13:26 [Devel] [PATCH hci-8.1 v4 00/11] dm-ploop: give back unused tail of top delta on suspend Alexander Ivanov
2026-10-12 13:26 ` [Devel] [PATCH hci-8.1 v4 01/11] dm-ploop: fix u32 overflow of the delta BAT byte size Alexander Ivanov
2026-10-12 13:33   ` no-reply
2026-10-13  6:42     ` Alexander Ivanov
2026-10-13  7:00       ` Alexander Ivanov
2026-10-12 13:26 ` [Devel] [PATCH hci-8.1 v4 02/11] dm-ploop: fix lost wakeup in ploop_allocator() Alexander Ivanov
2026-10-12 13:30   ` no-reply
2026-10-12 13:26 ` [Devel] [PATCH hci-8.1 v4 03/11] dm-ploop: reject a delta header whose BAT does not cover the target Alexander Ivanov
2026-10-12 13:31   ` no-reply
2026-10-12 13:26 ` [Devel] [PATCH hci-8.1 v4 04/11] dm-ploop: reject empty deltas Alexander Ivanov
2026-10-12 13:32   ` no-reply
2026-10-12 13:26 ` [Devel] [PATCH hci-8.1 v4 05/11] dm-ploop: set delta is_raw before applying its mappings Alexander Ivanov
2026-10-12 13:34   ` no-reply
2026-10-12 13:26 ` [Devel] [PATCH hci-8.1 v4 06/11] dm-ploop: factor out ploop_read_delta() from ploop_add_delta() Alexander Ivanov
2026-10-12 13:34   ` no-reply
2026-10-12 13:26 ` [Devel] [PATCH hci-8.1 v4 07/11] dm-ploop: take bat_lock around md page lookup in ploop_llseek_hole() Alexander Ivanov
2026-10-12 13:36   ` no-reply
2026-10-12 13:26 ` [Devel] [PATCH hci-8.1 v4 08/11] dm-ploop: use wake_up() for inflight_md_wq and dispatcher_wq_prealloc Alexander Ivanov
2026-10-12 13:35   ` no-reply
2026-10-12 13:26 ` Alexander Ivanov [this message]
2026-10-12 13:40   ` [Devel] [PATCH hci-8.1 v4 09/11] dm-ploop: fix use-after-free on the last inflight_md decrement no-reply
2026-10-13  6:54     ` Alexander Ivanov
2026-10-12 13:26 ` [Devel] [PATCH hci-8.1 v4 10/11] dm-ploop: reload metadata on resume Alexander Ivanov
2026-10-12 13:44   ` no-reply
2026-10-13  7:04     ` Alexander Ivanov
2026-10-12 13:26 ` [Devel] [PATCH hci-8.1 v4 11/11] dm-ploop: truncate unused tail of top delta on suspend Alexander Ivanov
2026-10-12 13:47   ` no-reply
2026-10-13  7:08     ` Alexander Ivanov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261012132646.41494-10-alexander.ivanov@virtuozzo.com \
    --to=alexander.ivanov@virtuozzo.com \
    --cc=den@openvz.org \
    --cc=devel@openvz.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.