]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
xen/blkfront: harden blkfront against event channel storms
authorJuergen Gross <jgross@suse.com>
Thu, 16 Dec 2021 07:24:08 +0000 (08:24 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 22 Dec 2021 08:04:19 +0000 (09:04 +0100)
commit 0fd08a34e8e3b67ec9bd8287ac0facf8374b844a upstream.

The Xen blkfront driver is still vulnerable for an attack via excessive
number of events sent by the backend. Fix that by using lateeoi event
channels.

This is part of XSA-391

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/block/xen-blkfront.c

index b27917dfdcc05193944fe05e8a77dbdad20b2156..1e44b7880200d0765b59babef143a11b3b9929c8 100644 (file)
@@ -1319,11 +1319,13 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
        unsigned long flags;
        struct blkfront_info *info = (struct blkfront_info *)dev_id;
        int error;
+       unsigned int eoiflag = XEN_EOI_FLAG_SPURIOUS;
 
        spin_lock_irqsave(&info->io_lock, flags);
 
        if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) {
                spin_unlock_irqrestore(&info->io_lock, flags);
+               xen_irq_lateeoi(irq, XEN_EOI_FLAG_SPURIOUS);
                return IRQ_HANDLED;
        }
 
@@ -1340,6 +1342,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
                unsigned long id;
                unsigned int op;
 
+               eoiflag = 0;
+
                RING_COPY_RESPONSE(&info->ring, i, &bret);
                id   = bret.id;
 
@@ -1444,6 +1448,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
 
        spin_unlock_irqrestore(&info->io_lock, flags);
 
+       xen_irq_lateeoi(irq, eoiflag);
+
        return IRQ_HANDLED;
 
  err:
@@ -1451,6 +1457,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
 
        spin_unlock_irqrestore(&info->io_lock, flags);
 
+       /* No EOI in order to avoid further interrupts. */
+
        pr_alert("%s disabled for further use\n", info->gd->disk_name);
        return IRQ_HANDLED;
 }
@@ -1489,8 +1497,8 @@ static int setup_blkring(struct xenbus_device *dev,
        if (err)
                goto fail;
 
-       err = bind_evtchn_to_irqhandler(info->evtchn, blkif_interrupt, 0,
-                                       "blkif", info);
+       err = bind_evtchn_to_irqhandler_lateeoi(info->evtchn, blkif_interrupt,
+                                               0, "blkif", info);
        if (err <= 0) {
                xenbus_dev_fatal(dev, err,
                                 "bind_evtchn_to_irqhandler failed");