* [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 related [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).