All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Michael S. Tsirkin" <mst@redhat.com>
To: Jason Wang <jasowang@redhat.com>
Cc: Jakub Kicinski <kuba@kernel.org>, netdev <netdev@vger.kernel.org>,
	davem <davem@davemloft.net>,
	linux-kernel <linux-kernel@vger.kernel.org>,
	virtualization <virtualization@lists.linux-foundation.org>
Subject: Re: [PATCH] virtio-net: fix race between ndo_open() and virtio_device_ready()
Date: Fri, 17 Jun 2022 08:32:55 -0400	[thread overview]
Message-ID: <20220617083141-mutt-send-email-mst@kernel.org> (raw)
In-Reply-To: <CACGkMEtTVs5W+qqt9Z6BcorJ6wcqcnSVuCBrHrLZbbKzG-7ULQ@mail.gmail.com>

On Fri, Jun 17, 2022 at 07:46:23PM +0800, Jason Wang wrote:
> On Fri, Jun 17, 2022 at 6:13 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> >
> > On Fri, Jun 17, 2022 at 03:29:49PM +0800, Jason Wang wrote:
> > > We used to call virtio_device_ready() after netdev registration. This
> > > cause a race between ndo_open() and virtio_device_ready(): if
> > > ndo_open() is called before virtio_device_ready(), the driver may
> > > start to use the device before DRIVER_OK which violates the spec.
> > >
> > > Fixing this by switching to use register_netdevice() and protect the
> > > virtio_device_ready() with rtnl_lock() to make sure ndo_open() can
> > > only be called after virtio_device_ready().
> > >
> > > Fixes: 4baf1e33d0842 ("virtio_net: enable VQs early")
> > > Signed-off-by: Jason Wang <jasowang@redhat.com>
> > > ---
> > >  drivers/net/virtio_net.c | 8 +++++++-
> > >  1 file changed, 7 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> > > index db05b5e930be..8a5810bcb839 100644
> > > --- a/drivers/net/virtio_net.c
> > > +++ b/drivers/net/virtio_net.c
> > > @@ -3655,14 +3655,20 @@ static int virtnet_probe(struct virtio_device *vdev)
> > >       if (vi->has_rss || vi->has_rss_hash_report)
> > >               virtnet_init_default_rss(vi);
> > >
> > > -     err = register_netdev(dev);
> > > +     /* serialize netdev register + virtio_device_ready() with ndo_open() */
> > > +     rtnl_lock();
> > > +
> > > +     err = register_netdevice(dev);
> > >       if (err) {
> > >               pr_debug("virtio_net: registering device failed\n");
> > > +             rtnl_unlock();
> > >               goto free_failover;
> > >       }
> > >
> > >       virtio_device_ready(vdev);
> > >
> > > +     rtnl_unlock();
> > > +
> > >       err = virtnet_cpu_notif_add(vi);
> > >       if (err) {
> > >               pr_debug("virtio_net: registering cpu notifier failed\n");
> >
> >
> > Looks good but then don't we have the same issue when removing the
> > device?
> >
> > Actually I looked at  virtnet_remove and I see
> >         unregister_netdev(vi->dev);
> >
> >         net_failover_destroy(vi->failover);
> >
> >         remove_vq_common(vi); <- this will reset the device
> >
> > a window here?
> 
> Probably. For safety, we probably need to reset before unregistering.


careful not to create new races, let's analyse this one to be
sure first.

> >
> >
> > Really, I think what we had originally was a better idea -
> > instead of dropping interrupts they were delayed and
> > when driver is ready to accept them it just enables them.
> 
> The problem is that it works only on some specific setup:
> 
> - doesn't work on shared IRQ
> - doesn't work on some specific driver e.g virtio-blk

can some core irq work fix that?

> > We just need to make sure driver does not wait for
> > interrupts before enabling them.
> >
> > And I suspect we need to make this opt-in on a per driver
> > basis.
> 
> Exactly.
> 
> Thanks
> 
> >
> >
> >
> > > --
> > > 2.25.1
> >

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

WARNING: multiple messages have this Message-ID (diff)
From: "Michael S. Tsirkin" <mst@redhat.com>
To: Jason Wang <jasowang@redhat.com>
Cc: davem <davem@davemloft.net>, Jakub Kicinski <kuba@kernel.org>,
	virtualization <virtualization@lists.linux-foundation.org>,
	netdev <netdev@vger.kernel.org>,
	linux-kernel <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH] virtio-net: fix race between ndo_open() and virtio_device_ready()
Date: Fri, 17 Jun 2022 08:32:55 -0400	[thread overview]
Message-ID: <20220617083141-mutt-send-email-mst@kernel.org> (raw)
In-Reply-To: <CACGkMEtTVs5W+qqt9Z6BcorJ6wcqcnSVuCBrHrLZbbKzG-7ULQ@mail.gmail.com>

On Fri, Jun 17, 2022 at 07:46:23PM +0800, Jason Wang wrote:
> On Fri, Jun 17, 2022 at 6:13 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> >
> > On Fri, Jun 17, 2022 at 03:29:49PM +0800, Jason Wang wrote:
> > > We used to call virtio_device_ready() after netdev registration. This
> > > cause a race between ndo_open() and virtio_device_ready(): if
> > > ndo_open() is called before virtio_device_ready(), the driver may
> > > start to use the device before DRIVER_OK which violates the spec.
> > >
> > > Fixing this by switching to use register_netdevice() and protect the
> > > virtio_device_ready() with rtnl_lock() to make sure ndo_open() can
> > > only be called after virtio_device_ready().
> > >
> > > Fixes: 4baf1e33d0842 ("virtio_net: enable VQs early")
> > > Signed-off-by: Jason Wang <jasowang@redhat.com>
> > > ---
> > >  drivers/net/virtio_net.c | 8 +++++++-
> > >  1 file changed, 7 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> > > index db05b5e930be..8a5810bcb839 100644
> > > --- a/drivers/net/virtio_net.c
> > > +++ b/drivers/net/virtio_net.c
> > > @@ -3655,14 +3655,20 @@ static int virtnet_probe(struct virtio_device *vdev)
> > >       if (vi->has_rss || vi->has_rss_hash_report)
> > >               virtnet_init_default_rss(vi);
> > >
> > > -     err = register_netdev(dev);
> > > +     /* serialize netdev register + virtio_device_ready() with ndo_open() */
> > > +     rtnl_lock();
> > > +
> > > +     err = register_netdevice(dev);
> > >       if (err) {
> > >               pr_debug("virtio_net: registering device failed\n");
> > > +             rtnl_unlock();
> > >               goto free_failover;
> > >       }
> > >
> > >       virtio_device_ready(vdev);
> > >
> > > +     rtnl_unlock();
> > > +
> > >       err = virtnet_cpu_notif_add(vi);
> > >       if (err) {
> > >               pr_debug("virtio_net: registering cpu notifier failed\n");
> >
> >
> > Looks good but then don't we have the same issue when removing the
> > device?
> >
> > Actually I looked at  virtnet_remove and I see
> >         unregister_netdev(vi->dev);
> >
> >         net_failover_destroy(vi->failover);
> >
> >         remove_vq_common(vi); <- this will reset the device
> >
> > a window here?
> 
> Probably. For safety, we probably need to reset before unregistering.


careful not to create new races, let's analyse this one to be
sure first.

> >
> >
> > Really, I think what we had originally was a better idea -
> > instead of dropping interrupts they were delayed and
> > when driver is ready to accept them it just enables them.
> 
> The problem is that it works only on some specific setup:
> 
> - doesn't work on shared IRQ
> - doesn't work on some specific driver e.g virtio-blk

can some core irq work fix that?

> > We just need to make sure driver does not wait for
> > interrupts before enabling them.
> >
> > And I suspect we need to make this opt-in on a per driver
> > basis.
> 
> Exactly.
> 
> Thanks
> 
> >
> >
> >
> > > --
> > > 2.25.1
> >


  reply	other threads:[~2022-06-17 12:33 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-17  7:29 [PATCH] virtio-net: fix race between ndo_open() and virtio_device_ready() Jason Wang
2022-06-17  7:29 ` Jason Wang
2022-06-17 10:12 ` Michael S. Tsirkin
2022-06-17 10:12   ` Michael S. Tsirkin
2022-06-17 11:46   ` Jason Wang
2022-06-17 11:46     ` Jason Wang
2022-06-17 12:32     ` Michael S. Tsirkin [this message]
2022-06-17 12:32       ` Michael S. Tsirkin
2022-06-20  3:34       ` Jason Wang
2022-06-20  3:34         ` Jason Wang
2022-06-27  6:33 ` Jason Wang
2022-06-27  6:33   ` 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=20220617083141-mutt-send-email-mst@kernel.org \
    --to=mst@redhat.com \
    --cc=davem@davemloft.net \
    --cc=jasowang@redhat.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --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.