linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] virtio: Don't access device data after unregistration.
@ 2012-09-03 13:50 sjur.brandeland
  2012-09-03 14:14 ` Michael S. Tsirkin
  0 siblings, 1 reply; 6+ messages in thread
From: sjur.brandeland @ 2012-09-03 13:50 UTC (permalink / raw)
  To: Rusty Russell
  Cc: Sjur Brændeland, linux-kernel, Sjur Brændeland,
	Guzman Lugo, Fernadndo, Michael S. Tsirkin, virtualization,
	Ohad Ben-Cohen

From: Sjur Brændeland <sjur.brandeland@stericsson.com>

Fix panic in virtio.c when CONFIG_DEBUG_SLAB is set.
Use device_del() and put_device() instead of
device_unregister(), and access device data before
calling put_device().


Signed-off-by: Sjur Brændeland <sjur.brandeland@stericsson.com>
cc: Guzman Lugo, Fernadndo <fernando.lugo@ti.com>
cc: Michael S. Tsirkin <mst@redhat.com>
cc: virtualization@lists.linux-foundation.org
cc: Ohad Ben-Cohen <ohad@wizery.com>
---
 drivers/virtio/virtio.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index c3b3f7f..71eacd1 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -225,8 +225,9 @@ EXPORT_SYMBOL_GPL(register_virtio_device);
 
 void unregister_virtio_device(struct virtio_device *dev)
 {
-	device_unregister(&dev->dev);
+	device_del(&dev->dev);
 	ida_simple_remove(&virtio_index_ida, dev->index);
+	put_device(&dev->dev);
 }
 EXPORT_SYMBOL_GPL(unregister_virtio_device);
 
-- 
1.7.5.4


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] virtio: Don't access device data after unregistration.
  2012-09-03 13:50 [PATCH] virtio: Don't access device data after unregistration sjur.brandeland
@ 2012-09-03 14:14 ` Michael S. Tsirkin
  2012-09-03 14:50   ` Sjur Brændeland
  0 siblings, 1 reply; 6+ messages in thread
From: Michael S. Tsirkin @ 2012-09-03 14:14 UTC (permalink / raw)
  To: sjur.brandeland
  Cc: Rusty Russell, Sjur Brændeland, linux-kernel, Guzman Lugo,
	Fernadndo, virtualization, Ohad Ben-Cohen

On Mon, Sep 03, 2012 at 03:50:42PM +0200, sjur.brandeland@stericsson.com wrote:
> From: Sjur Brændeland <sjur.brandeland@stericsson.com>
> 
> Fix panic in virtio.c when CONFIG_DEBUG_SLAB is set.

What's the root cause of the panic?


> Use device_del() and put_device() instead of
> device_unregister(), and access device data before
> calling put_device().

Why does this help? Does device_unregister free the
device so dev->index access crashes?
If yes virtio_pci_remove will crash too
as it accesses the device after the
call to unregister_virtio_device so the
fix won't be effective.

> Signed-off-by: Sjur Brændeland <sjur.brandeland@stericsson.com>
> cc: Guzman Lugo, Fernadndo <fernando.lugo@ti.com>
> cc: Michael S. Tsirkin <mst@redhat.com>
> cc: virtualization@lists.linux-foundation.org
> cc: Ohad Ben-Cohen <ohad@wizery.com>
> ---
>  drivers/virtio/virtio.c |    3 ++-
>  1 files changed, 2 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
> index c3b3f7f..71eacd1 100644
> --- a/drivers/virtio/virtio.c
> +++ b/drivers/virtio/virtio.c
> @@ -225,8 +225,9 @@ EXPORT_SYMBOL_GPL(register_virtio_device);
>  
>  void unregister_virtio_device(struct virtio_device *dev)
>  {
> -	device_unregister(&dev->dev);
> +	device_del(&dev->dev);
>  	ida_simple_remove(&virtio_index_ida, dev->index);
> +	put_device(&dev->dev);
>  }
>  EXPORT_SYMBOL_GPL(unregister_virtio_device);
>  
> -- 
> 1.7.5.4

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] virtio: Don't access device data after unregistration.
  2012-09-03 14:14 ` Michael S. Tsirkin
@ 2012-09-03 14:50   ` Sjur Brændeland
  2012-09-03 20:18     ` Michael S. Tsirkin
  0 siblings, 1 reply; 6+ messages in thread
From: Sjur Brændeland @ 2012-09-03 14:50 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Rusty Russell, linux-kernel, Guzman Lugo, Fernadndo,
	virtualization, Ohad Ben-Cohen

Hi Michael,

>> Fix panic in virtio.c when CONFIG_DEBUG_SLAB is set.
>
> What's the root cause of the panic?

I believe the cause of the panic is calling
ida_simple_remove(&virtio_index_ida, dev->index);
when the dev structure is "poisoned" after kfree.
It might be the "BUG_ON((int)id < 0)" that bites...

>> Use device_del() and put_device() instead of
>> device_unregister(), and access device data before
>> calling put_device().

> Why does this help? Does device_unregister free the
> device so dev->index access crashes?

Yes, if device ref-count is one when calling unregister
the device is freed.

> If yes virtio_pci_remove will crash too
> as it accesses the device after the
> call to unregister_virtio_device so the
> fix won't be effective.

I discovered this using the remoteproc framework.
It might be that device is unregistered with ref-count greater
than one normally, in that case this bug will not show up.

Regards,
Sjur

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] virtio: Don't access device data after unregistration.
  2012-09-03 14:50   ` Sjur Brændeland
@ 2012-09-03 20:18     ` Michael S. Tsirkin
  2012-09-04 12:12       ` Sjur Brændeland
  0 siblings, 1 reply; 6+ messages in thread
From: Michael S. Tsirkin @ 2012-09-03 20:18 UTC (permalink / raw)
  To: Sjur Brændeland
  Cc: Rusty Russell, linux-kernel, Guzman Lugo, Fernadndo,
	virtualization, Ohad Ben-Cohen

On Mon, Sep 03, 2012 at 04:50:10PM +0200, Sjur Brændeland wrote:
> Hi Michael,
> 
> >> Fix panic in virtio.c when CONFIG_DEBUG_SLAB is set.
> >
> > What's the root cause of the panic?
> 
> I believe the cause of the panic is calling
> ida_simple_remove(&virtio_index_ida, dev->index);
> when the dev structure is "poisoned" after kfree.
> It might be the "BUG_ON((int)id < 0)" that bites...
> 
> >> Use device_del() and put_device() instead of
> >> device_unregister(), and access device data before
> >> calling put_device().
> 
> > Why does this help? Does device_unregister free the
> > device so dev->index access crashes?
> 
> Yes, if device ref-count is one when calling unregister
> the device is freed.

Interesting. Where exactly? Note that:

struct rproc_vdev {
        struct list_head node;
        struct rproc *rproc;
        struct virtio_device vdev;
        struct rproc_vring vring[RVDEV_NUM_VRINGS];
        unsigned long dfeatures;
        unsigned long gfeatures;
};              

kfree(&proc_vdev->vdev) is unlikely to be the right thing to do.

> > If yes virtio_pci_remove will crash too
> > as it accesses the device after the
> > call to unregister_virtio_device so the
> > fix won't be effective.
> 
> I discovered this using the remoteproc framework.
> It might be that device is unregistered with ref-count greater
> than one normally, in that case this bug will not show up.
> 
> Regards,
> Sjur

It might be remoteproc has an unrelated bug?

-- 
MST

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] virtio: Don't access device data after unregistration.
  2012-09-03 20:18     ` Michael S. Tsirkin
@ 2012-09-04 12:12       ` Sjur Brændeland
  2012-09-04 14:13         ` Michael S. Tsirkin
  0 siblings, 1 reply; 6+ messages in thread
From: Sjur Brændeland @ 2012-09-04 12:12 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Rusty Russell, linux-kernel, Guzman Lugo, Fernadndo,
	virtualization, Ohad Ben-Cohen

Hi Michael,

>> >> Fix panic in virtio.c when CONFIG_DEBUG_SLAB is set.
>> >
>> > What's the root cause of the panic?
>>
>> I believe the cause of the panic is calling
>> ida_simple_remove(&virtio_index_ida, dev->index);
>> when the dev structure is "poisoned" after kfree.
>> It might be the "BUG_ON((int)id < 0)" that bites...
>>
>> >> Use device_del() and put_device() instead of
>> >> device_unregister(), and access device data before
>> >> calling put_device().
>>
>> > Why does this help? Does device_unregister free the
>> > device so dev->index access crashes?
>>
>> Yes, if device ref-count is one when calling unregister
>> the device is freed.
>
> Interesting. Where exactly?...

I was wrong here, the reason is not related to ref-count being
above one. The reason this issue do not show up in virtio_pci
is that the release function is a dummy:

[snip]
static void virtio_pci_release_dev(struct device *_d)
{
	/*
	 * No need for a release method as we allocate/free
	 * all devices together with the pci devices.
	 * Provide an empty one to avoid getting a warning from core.
	 */
}

The device structure uses a kref for reference counting the device.
In virtio_pci() the release function virtio_pci_release_dev()
will be called when the device is unregistered, but because the
release function is dummy, data isn't freed or reset at this point.
So for virtio devices created from virtio_pci my patch is not
currently needed.

However, empty release functions are not the preferred way, e.g look at
https://lkml.org/lkml/2012/4/3/301

[Greg K.H:]
> > > > +static void hsi_port_release(struct device *dev __maybe_unused)
> > > > +{
> > > > +}
> > >
> > > As per the documentation in the kernel tree, I get to mock you
> > > mercilessly for doing something as foolish as this.  You are not smarter
> > > than the kernel and don't think that you got rid of the kernel warning
> > > properly by doing this.  Do you think that I wrote that code for no good
> > > reason?  The kernel was being nice and telling you what you did wrong,
> > > don't try to fake it out, it's smarter than you are here.

But remoteproc frees the device memory in the release function
rproc_vdev_release() and needs this patch.

Regards,
Sjur

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] virtio: Don't access device data after unregistration.
  2012-09-04 12:12       ` Sjur Brændeland
@ 2012-09-04 14:13         ` Michael S. Tsirkin
  0 siblings, 0 replies; 6+ messages in thread
From: Michael S. Tsirkin @ 2012-09-04 14:13 UTC (permalink / raw)
  To: Sjur Brændeland
  Cc: Rusty Russell, linux-kernel, Guzman Lugo, Fernadndo,
	virtualization, Ohad Ben-Cohen

On Tue, Sep 04, 2012 at 02:12:33PM +0200, Sjur Brændeland wrote:
> Hi Michael,
> 
> >> >> Fix panic in virtio.c when CONFIG_DEBUG_SLAB is set.
> >> >
> >> > What's the root cause of the panic?
> >>
> >> I believe the cause of the panic is calling
> >> ida_simple_remove(&virtio_index_ida, dev->index);
> >> when the dev structure is "poisoned" after kfree.
> >> It might be the "BUG_ON((int)id < 0)" that bites...
> >>
> >> >> Use device_del() and put_device() instead of
> >> >> device_unregister(), and access device data before
> >> >> calling put_device().
> >>
> >> > Why does this help? Does device_unregister free the
> >> > device so dev->index access crashes?
> >>
> >> Yes, if device ref-count is one when calling unregister
> >> the device is freed.
> >
> > Interesting. Where exactly?...
> 
> I was wrong here, the reason is not related to ref-count being
> above one. The reason this issue do not show up in virtio_pci
> is that the release function is a dummy:
> 
> [snip]
> static void virtio_pci_release_dev(struct device *_d)
> {
> 	/*
> 	 * No need for a release method as we allocate/free
> 	 * all devices together with the pci devices.
> 	 * Provide an empty one to avoid getting a warning from core.
> 	 */
> }
> 
> The device structure uses a kref for reference counting the device.
> In virtio_pci() the release function virtio_pci_release_dev()
> will be called when the device is unregistered, but because the
> release function is dummy, data isn't freed or reset at this point.
> So for virtio devices created from virtio_pci my patch is not
> currently needed.
> 
> However, empty release functions are not the preferred way, e.g look at
> https://lkml.org/lkml/2012/4/3/301
> 
> [Greg K.H:]
> > > > > +static void hsi_port_release(struct device *dev __maybe_unused)
> > > > > +{
> > > > > +}
> > > >
> > > > As per the documentation in the kernel tree, I get to mock you
> > > > mercilessly for doing something as foolish as this.  You are not smarter
> > > > than the kernel and don't think that you got rid of the kernel warning
> > > > properly by doing this.  Do you think that I wrote that code for no good
> > > > reason?  The kernel was being nice and telling you what you did wrong,
> > > > don't try to fake it out, it's smarter than you are here.
> 
> But remoteproc frees the device memory in the release function
> rproc_vdev_release() and needs this patch.
> 
> Regards,
> Sjur


Okay, so let's add a comment in virtio in unregister
function. Also slightly preferable to just use device_unregister
IMHO. Something like the below?

	/*
	   device_unregister drops reference to device so put_device could
	   invoke release callback. In case that callback will free the device,
	   make sure we don't access device after this call.
	 */

	int index = dev->index;
        device_unregister(&dev->dev);
        ida_simple_remove(&virtio_index_ida, index);

-- 
MST

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2012-09-04 14:12 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-03 13:50 [PATCH] virtio: Don't access device data after unregistration sjur.brandeland
2012-09-03 14:14 ` Michael S. Tsirkin
2012-09-03 14:50   ` Sjur Brændeland
2012-09-03 20:18     ` Michael S. Tsirkin
2012-09-04 12:12       ` Sjur Brændeland
2012-09-04 14:13         ` Michael S. Tsirkin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).