On 03/05/17 12:45, Steven Haigh wrote:
> Just wanted to give this a little nudge now people seem to be back on
> deck...

Glenn, could you please give the attached patch a try?

It should be applied on top of the other correction, the old debug
patch should not be applied.

I have added some debug output to make sure we see what is happening.


Juergen

commit 246aaf60bd934b7571944b98a31078d519d637c6
Author: Juergen Gross <jgr...@suse.com>
Date:   Wed May 3 15:57:18 2017 +0200

    xen/blkback: don't free be structure too early
    
    The be structure must nor be freed when freeing the blkif structure
    isn't done. Otherwise a use-after-free of be when unmapping the ring
    used for communicating with the frontend will occur in case of a
    late call of xenblk_disconnect() (e.g. due to an I/O still active
    when trying to disconnect).

diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index 411d2ded2456..0614fb294e2b 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -33,6 +33,7 @@ struct backend_info {
 	unsigned		major;
 	unsigned		minor;
 	char			*mode;
+	int			delayed;
 };
 
 static struct kmem_cache *xen_blkif_cachep;
@@ -262,8 +263,11 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
 		 * don't have any discard_io or other_io requests. So, checking
 		 * for inflight IO is enough.
 		 */
-		if (atomic_read(&ring->inflight) > 0)
+		if (atomic_read(&ring->inflight) > 0) {
+			pr_warn("xen_blkif_disconnect: busy\n");
+			blkif->be->delayed = 1;
 			return -EBUSY;
+		}
 
 		if (ring->irq) {
 			unbind_from_irqhandler(ring->irq, ring);
@@ -315,9 +319,11 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
 
 static void xen_blkif_free(struct xen_blkif *blkif)
 {
-
-	xen_blkif_disconnect(blkif);
+	pr_warn("xen_blkif_free: delayed = %d\n", blkif->be->delayed);
+	WARN_ON(xen_blkif_disconnect(blkif));
 	xen_vbd_free(&blkif->vbd);
+	kfree(blkif->be->mode);
+	kfree(blkif->be);
 
 	/* Make sure everything is drained before shutting down */
 	kmem_cache_free(xen_blkif_cachep, blkif);
@@ -512,8 +518,7 @@ static int xen_blkbk_remove(struct xenbus_device *dev)
 
 	/* Put the reference we set in xen_blkif_alloc(). */
 	xen_blkif_put(be->blkif);
-	kfree(be->mode);
-	kfree(be);
+
 	return 0;
 }
 
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

Reply via email to