All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jason Wang <jasowang@redhat.com>
To: "Michael S. Tsirkin" <mst@redhat.com>
Cc: virtualization <virtualization@lists.linux-foundation.org>,
	linux-kernel <linux-kernel@vger.kernel.org>,
	"Hetzelt, Felicitas" <f.hetzelt@tu-berlin.de>,
	"kaplan, david" <david.kaplan@amd.com>,
	Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>,
	Boqun Feng <boqun.feng@gmail.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Peter Zijlstra <peterz@infradead.org>,
	"Paul E . McKenney" <paulmck@kernel.org>
Subject: Re: [PATCH V2 07/12] virtio-pci: harden INTX interrupts
Date: Thu, 14 Oct 2021 14:20:17 +0800	[thread overview]
Message-ID: <CACGkMEvB4sMPmMmPQmHFasGLwktyXuCenQKGuoajmoFQYJJeBQ@mail.gmail.com> (raw)
In-Reply-To: <20211014014551-mutt-send-email-mst@kernel.org>

On Thu, Oct 14, 2021 at 1:50 PM Michael S. Tsirkin <mst@redhat.com> wrote:
>
> On Thu, Oct 14, 2021 at 10:35:48AM +0800, Jason Wang wrote:
> > On Wed, Oct 13, 2021 at 5:42 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> > >
> > > On Tue, Oct 12, 2021 at 02:52:22PM +0800, Jason Wang wrote:
> > > > This patch tries to make sure the virtio interrupt handler for INTX
> > > > won't be called after a reset and before virtio_device_ready(). We
> > > > can't use IRQF_NO_AUTOEN since we're using shared interrupt
> > > > (IRQF_SHARED). So this patch tracks the INTX enabling status in a new
> > > > intx_soft_enabled variable and toggle it during in
> > > > vp_disable/enable_vectors(). The INTX interrupt handler will check
> > > > intx_soft_enabled before processing the actual interrupt.
> > > >
> > > > Cc: Boqun Feng <boqun.feng@gmail.com>
> > > > Cc: Thomas Gleixner <tglx@linutronix.de>
> > > > Cc: Peter Zijlstra <peterz@infradead.org>
> > > > Cc: Paul E. McKenney <paulmck@kernel.org>
> > > > Signed-off-by: Jason Wang <jasowang@redhat.com>
> > > > ---
> > > >  drivers/virtio/virtio_pci_common.c | 24 ++++++++++++++++++++++--
> > > >  drivers/virtio/virtio_pci_common.h |  1 +
> > > >  2 files changed, 23 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> > > > index 0b9523e6dd39..5ae6a2a4eb77 100644
> > > > --- a/drivers/virtio/virtio_pci_common.c
> > > > +++ b/drivers/virtio/virtio_pci_common.c
> > > > @@ -30,8 +30,16 @@ void vp_disable_vectors(struct virtio_device *vdev)
> > > >       struct virtio_pci_device *vp_dev = to_vp_device(vdev);
> > > >       int i;
> > > >
> > > > -     if (vp_dev->intx_enabled)
> > > > +     if (vp_dev->intx_enabled) {
> > > > +             /*
> > > > +              * The below synchronize() guarantees that any
> > > > +              * interrupt for this line arriving after
> > > > +              * synchronize_irq() has completed is guaranteed to see
> > > > +              * intx_soft_enabled == false.
> > > > +              */
> > > > +             WRITE_ONCE(vp_dev->intx_soft_enabled, false);
> > > >               synchronize_irq(vp_dev->pci_dev->irq);
> > > > +     }
> > > >
> > > >       for (i = 0; i < vp_dev->msix_vectors; ++i)
> > > >               disable_irq(pci_irq_vector(vp_dev->pci_dev, i));
> > > > @@ -43,8 +51,16 @@ void vp_enable_vectors(struct virtio_device *vdev)
> > > >       struct virtio_pci_device *vp_dev = to_vp_device(vdev);
> > > >       int i;
> > > >
> > > > -     if (vp_dev->intx_enabled)
> > > > +     if (vp_dev->intx_enabled) {
> > > > +             disable_irq(vp_dev->pci_dev->irq);
> > > > +             /*
> > > > +              * The above disable_irq() provides TSO ordering and
> > > > +              * as such promotes the below store to store-release.
> > > > +              */
> > > > +             WRITE_ONCE(vp_dev->intx_soft_enabled, true);
> > > > +             enable_irq(vp_dev->pci_dev->irq);
> > > >               return;
> > > > +     }
> > > >
> > > >       for (i = 0; i < vp_dev->msix_vectors; ++i)
> > > >               enable_irq(pci_irq_vector(vp_dev->pci_dev, i));
> > > > @@ -97,6 +113,10 @@ static irqreturn_t vp_interrupt(int irq, void *opaque)
> > > >       struct virtio_pci_device *vp_dev = opaque;
> > > >       u8 isr;
> > > >
> > > > +     /* read intx_soft_enabled before read others */
> > > > +     if (!smp_load_acquire(&vp_dev->intx_soft_enabled))
> > > > +             return IRQ_NONE;
> > > > +
> > > >       /* reading the ISR has the effect of also clearing it so it's very
> > > >        * important to save off the value. */
> > > >       isr = ioread8(vp_dev->isr);
> > >
> > > I don't see why we need this ordering guarantee here.
> > >
> > > synchronize_irq above makes sure no interrupt handler
> > > is in progress.
> >
> > Yes.
> >
> > > the handler itself thus does not need
> > > any specific order, it is ok if intx_soft_enabled is read
> > > after, not before the rest of it.
> >
> > But the interrupt could be raised after synchronize_irq() which may
> > see a false of the intx_soft_enabled.
>
> You mean a "true" value right? false is what we are writing there.

I meant that we want to not go for stuff like vq->callback after the
synchronize_irq() after setting intx_soft_enabled to false. Otherwise
we may get unexpected results like use after free. Host can craft ISR
in this case.

>
> Are you sure it can happen? I think that synchronize_irq makes the value
> visible on all CPUs running the irq.

Yes, so the false is visible by vp_interrupt(), we can't do the other
task before we check intx_soft_enabled.

>
> > In this case we still need the
> > make sure intx_soft_enbled to be read first instead of allowing other
> > operations to be done first, otherwise the intx_soft_enabled is
> > meaningless.
> >
> > Thanks
>
> If intx_soft_enbled were not visible after synchronize_irq then
> it does not matter in which order we read it wrt other values,
> it still wouldn't work right.

Yes.

Thanks

>
> > >
> > > Just READ_ONCE should be enough, and we can drop the comment.
> > >
> > >
> > > > diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
> > > > index a235ce9ff6a5..3c06e0f92ee4 100644
> > > > --- a/drivers/virtio/virtio_pci_common.h
> > > > +++ b/drivers/virtio/virtio_pci_common.h
> > > > @@ -64,6 +64,7 @@ struct virtio_pci_device {
> > > >       /* MSI-X support */
> > > >       int msix_enabled;
> > > >       int intx_enabled;
> > > > +     bool intx_soft_enabled;
> > > >       cpumask_var_t *msix_affinity_masks;
> > > >       /* Name strings for interrupts. This size should be enough,
> > > >        * and I'm too lazy to allocate each name separately. */
> > > > --
> > > > 2.25.1
> > >
>


WARNING: multiple messages have this Message-ID (diff)
From: Jason Wang <jasowang@redhat.com>
To: "Michael S. Tsirkin" <mst@redhat.com>
Cc: "Paul E . McKenney" <paulmck@kernel.org>,
	"kaplan, david" <david.kaplan@amd.com>,
	Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>,
	Peter Zijlstra <peterz@infradead.org>,
	Boqun Feng <boqun.feng@gmail.com>,
	"Hetzelt, Felicitas" <f.hetzelt@tu-berlin.de>,
	linux-kernel <linux-kernel@vger.kernel.org>,
	virtualization <virtualization@lists.linux-foundation.org>,
	Thomas Gleixner <tglx@linutronix.de>
Subject: Re: [PATCH V2 07/12] virtio-pci: harden INTX interrupts
Date: Thu, 14 Oct 2021 14:20:17 +0800	[thread overview]
Message-ID: <CACGkMEvB4sMPmMmPQmHFasGLwktyXuCenQKGuoajmoFQYJJeBQ@mail.gmail.com> (raw)
In-Reply-To: <20211014014551-mutt-send-email-mst@kernel.org>

On Thu, Oct 14, 2021 at 1:50 PM Michael S. Tsirkin <mst@redhat.com> wrote:
>
> On Thu, Oct 14, 2021 at 10:35:48AM +0800, Jason Wang wrote:
> > On Wed, Oct 13, 2021 at 5:42 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> > >
> > > On Tue, Oct 12, 2021 at 02:52:22PM +0800, Jason Wang wrote:
> > > > This patch tries to make sure the virtio interrupt handler for INTX
> > > > won't be called after a reset and before virtio_device_ready(). We
> > > > can't use IRQF_NO_AUTOEN since we're using shared interrupt
> > > > (IRQF_SHARED). So this patch tracks the INTX enabling status in a new
> > > > intx_soft_enabled variable and toggle it during in
> > > > vp_disable/enable_vectors(). The INTX interrupt handler will check
> > > > intx_soft_enabled before processing the actual interrupt.
> > > >
> > > > Cc: Boqun Feng <boqun.feng@gmail.com>
> > > > Cc: Thomas Gleixner <tglx@linutronix.de>
> > > > Cc: Peter Zijlstra <peterz@infradead.org>
> > > > Cc: Paul E. McKenney <paulmck@kernel.org>
> > > > Signed-off-by: Jason Wang <jasowang@redhat.com>
> > > > ---
> > > >  drivers/virtio/virtio_pci_common.c | 24 ++++++++++++++++++++++--
> > > >  drivers/virtio/virtio_pci_common.h |  1 +
> > > >  2 files changed, 23 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> > > > index 0b9523e6dd39..5ae6a2a4eb77 100644
> > > > --- a/drivers/virtio/virtio_pci_common.c
> > > > +++ b/drivers/virtio/virtio_pci_common.c
> > > > @@ -30,8 +30,16 @@ void vp_disable_vectors(struct virtio_device *vdev)
> > > >       struct virtio_pci_device *vp_dev = to_vp_device(vdev);
> > > >       int i;
> > > >
> > > > -     if (vp_dev->intx_enabled)
> > > > +     if (vp_dev->intx_enabled) {
> > > > +             /*
> > > > +              * The below synchronize() guarantees that any
> > > > +              * interrupt for this line arriving after
> > > > +              * synchronize_irq() has completed is guaranteed to see
> > > > +              * intx_soft_enabled == false.
> > > > +              */
> > > > +             WRITE_ONCE(vp_dev->intx_soft_enabled, false);
> > > >               synchronize_irq(vp_dev->pci_dev->irq);
> > > > +     }
> > > >
> > > >       for (i = 0; i < vp_dev->msix_vectors; ++i)
> > > >               disable_irq(pci_irq_vector(vp_dev->pci_dev, i));
> > > > @@ -43,8 +51,16 @@ void vp_enable_vectors(struct virtio_device *vdev)
> > > >       struct virtio_pci_device *vp_dev = to_vp_device(vdev);
> > > >       int i;
> > > >
> > > > -     if (vp_dev->intx_enabled)
> > > > +     if (vp_dev->intx_enabled) {
> > > > +             disable_irq(vp_dev->pci_dev->irq);
> > > > +             /*
> > > > +              * The above disable_irq() provides TSO ordering and
> > > > +              * as such promotes the below store to store-release.
> > > > +              */
> > > > +             WRITE_ONCE(vp_dev->intx_soft_enabled, true);
> > > > +             enable_irq(vp_dev->pci_dev->irq);
> > > >               return;
> > > > +     }
> > > >
> > > >       for (i = 0; i < vp_dev->msix_vectors; ++i)
> > > >               enable_irq(pci_irq_vector(vp_dev->pci_dev, i));
> > > > @@ -97,6 +113,10 @@ static irqreturn_t vp_interrupt(int irq, void *opaque)
> > > >       struct virtio_pci_device *vp_dev = opaque;
> > > >       u8 isr;
> > > >
> > > > +     /* read intx_soft_enabled before read others */
> > > > +     if (!smp_load_acquire(&vp_dev->intx_soft_enabled))
> > > > +             return IRQ_NONE;
> > > > +
> > > >       /* reading the ISR has the effect of also clearing it so it's very
> > > >        * important to save off the value. */
> > > >       isr = ioread8(vp_dev->isr);
> > >
> > > I don't see why we need this ordering guarantee here.
> > >
> > > synchronize_irq above makes sure no interrupt handler
> > > is in progress.
> >
> > Yes.
> >
> > > the handler itself thus does not need
> > > any specific order, it is ok if intx_soft_enabled is read
> > > after, not before the rest of it.
> >
> > But the interrupt could be raised after synchronize_irq() which may
> > see a false of the intx_soft_enabled.
>
> You mean a "true" value right? false is what we are writing there.

I meant that we want to not go for stuff like vq->callback after the
synchronize_irq() after setting intx_soft_enabled to false. Otherwise
we may get unexpected results like use after free. Host can craft ISR
in this case.

>
> Are you sure it can happen? I think that synchronize_irq makes the value
> visible on all CPUs running the irq.

Yes, so the false is visible by vp_interrupt(), we can't do the other
task before we check intx_soft_enabled.

>
> > In this case we still need the
> > make sure intx_soft_enbled to be read first instead of allowing other
> > operations to be done first, otherwise the intx_soft_enabled is
> > meaningless.
> >
> > Thanks
>
> If intx_soft_enbled were not visible after synchronize_irq then
> it does not matter in which order we read it wrt other values,
> it still wouldn't work right.

Yes.

Thanks

>
> > >
> > > Just READ_ONCE should be enough, and we can drop the comment.
> > >
> > >
> > > > diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
> > > > index a235ce9ff6a5..3c06e0f92ee4 100644
> > > > --- a/drivers/virtio/virtio_pci_common.h
> > > > +++ b/drivers/virtio/virtio_pci_common.h
> > > > @@ -64,6 +64,7 @@ struct virtio_pci_device {
> > > >       /* MSI-X support */
> > > >       int msix_enabled;
> > > >       int intx_enabled;
> > > > +     bool intx_soft_enabled;
> > > >       cpumask_var_t *msix_affinity_masks;
> > > >       /* Name strings for interrupts. This size should be enough,
> > > >        * and I'm too lazy to allocate each name separately. */
> > > > --
> > > > 2.25.1
> > >
>

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

  reply	other threads:[~2021-10-14  6:20 UTC|newest]

Thread overview: 86+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-12  6:52 [PATCH V2 00/12] More virtio hardening Jason Wang
2021-10-12  6:52 ` Jason Wang
2021-10-12  6:52 ` [PATCH V2 01/12] virtio-blk: validate num_queues during probe Jason Wang
2021-10-12  6:52   ` Jason Wang
2021-10-13 10:04   ` Michael S. Tsirkin
2021-10-13 10:04     ` Michael S. Tsirkin
2021-10-14  2:32     ` Jason Wang
2021-10-14  2:32       ` Jason Wang
2021-10-14  5:45       ` Michael S. Tsirkin
2021-10-14  5:45         ` Michael S. Tsirkin
2021-10-14  6:23         ` Jason Wang
2021-10-14  6:23           ` Jason Wang
2021-10-12  6:52 ` [PATCH V2 02/12] virtio: add doc for validate() method Jason Wang
2021-10-12  6:52   ` Jason Wang
2021-10-13 10:09   ` Michael S. Tsirkin
2021-10-13 10:09     ` Michael S. Tsirkin
2021-10-14  2:32     ` Jason Wang
2021-10-14  2:32       ` Jason Wang
2021-10-12  6:52 ` [PATCH V2 03/12] virtio-console: switch to use .validate() Jason Wang
2021-10-12  6:52   ` Jason Wang
2021-10-13  9:50   ` Michael S. Tsirkin
2021-10-13  9:50     ` Michael S. Tsirkin
2021-10-14  2:28     ` Jason Wang
2021-10-14  2:28       ` Jason Wang
2021-10-14  5:58       ` Michael S. Tsirkin
2021-10-14  5:58         ` Michael S. Tsirkin
2021-10-12  6:52 ` [PATCH V2 04/12] virtio_console: validate max_nr_ports before trying to use it Jason Wang
2021-10-12  6:52   ` Jason Wang
2021-10-12  6:52 ` [PATCH V2 05/12] virtio_config: introduce a new ready method Jason Wang
2021-10-12  6:52   ` Jason Wang
2021-10-13  9:57   ` Michael S. Tsirkin
2021-10-13  9:57     ` Michael S. Tsirkin
2021-10-12  6:52 ` [PATCH V2 06/12] virtio_pci: harden MSI-X interrupts Jason Wang
2021-10-12  6:52   ` Jason Wang
2021-10-13  9:59   ` Michael S. Tsirkin
2021-10-13  9:59     ` Michael S. Tsirkin
2021-10-14  2:29     ` Jason Wang
2021-10-14  2:29       ` Jason Wang
2021-10-15 12:09   ` Dongli Zhang
2021-10-15 12:09     ` Dongli Zhang
2021-10-15 17:27     ` Michael S. Tsirkin
2021-10-15 17:27       ` Michael S. Tsirkin
2021-10-19  1:33       ` Jason Wang
2021-10-19  1:33         ` Jason Wang
2021-10-19 17:01         ` Dongli Zhang
2021-10-19 17:01           ` Dongli Zhang
2021-10-20  1:33           ` Jason Wang
2021-10-20  1:33             ` Jason Wang
2021-10-20  6:56             ` Michael S. Tsirkin
2021-10-20  6:56               ` Michael S. Tsirkin
2021-10-12  6:52 ` [PATCH V2 07/12] virtio-pci: harden INTX interrupts Jason Wang
2021-10-12  6:52   ` Jason Wang
2021-10-13  9:42   ` Michael S. Tsirkin
2021-10-13  9:42     ` Michael S. Tsirkin
2021-10-14  2:35     ` Jason Wang
2021-10-14  2:35       ` Jason Wang
2021-10-14  5:49       ` Michael S. Tsirkin
2021-10-14  5:49         ` Michael S. Tsirkin
2021-10-14  6:20         ` Jason Wang [this message]
2021-10-14  6:20           ` Jason Wang
2021-10-14  6:26           ` Michael S. Tsirkin
2021-10-14  6:26             ` Michael S. Tsirkin
2021-10-14  6:32             ` Jason Wang
2021-10-14  6:32               ` Jason Wang
2021-10-14  7:04               ` Michael S. Tsirkin
2021-10-14  7:04                 ` Michael S. Tsirkin
2021-10-14  7:12                 ` Jason Wang
2021-10-14  7:12                   ` Jason Wang
2021-10-14  9:25                   ` Michael S. Tsirkin
2021-10-14  9:25                     ` Michael S. Tsirkin
2021-10-14 10:03                     ` Jason Wang
2021-10-14 10:03                       ` Jason Wang
2021-10-12  6:52 ` [PATCH V2 08/12] virtio_ring: fix typos in vring_desc_extra Jason Wang
2021-10-12  6:52   ` Jason Wang
2021-10-12  6:52 ` [PATCH V2 09/12] virtio_ring: validate used buffer length Jason Wang
2021-10-12  6:52   ` Jason Wang
2021-10-13 10:02   ` Michael S. Tsirkin
2021-10-13 10:02     ` Michael S. Tsirkin
2021-10-14  2:30     ` Jason Wang
2021-10-14  2:30       ` Jason Wang
2021-10-12  6:52 ` [PATCH V2 10/12] virtio-net: don't let virtio core to validate used length Jason Wang
2021-10-12  6:52   ` Jason Wang
2021-10-12  6:52 ` [PATCH V2 11/12] virtio-blk: " Jason Wang
2021-10-12  6:52   ` Jason Wang
2021-10-12  6:52 ` [PATCH V2 12/12] virtio-scsi: don't let virtio core to validate used buffer length Jason Wang
2021-10-12  6:52   ` Jason Wang

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=CACGkMEvB4sMPmMmPQmHFasGLwktyXuCenQKGuoajmoFQYJJeBQ@mail.gmail.com \
    --to=jasowang@redhat.com \
    --cc=boqun.feng@gmail.com \
    --cc=david.kaplan@amd.com \
    --cc=f.hetzelt@tu-berlin.de \
    --cc=konrad.wilk@oracle.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mst@redhat.com \
    --cc=paulmck@kernel.org \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    --cc=virtualization@lists.linux-foundation.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.