All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hans Verkuil <hverkuil@xs4all.nl>
To: Greg KH <greg@kroah.com>
Cc: linux-kernel@vger.kernel.org, v4l <video4linux-list@redhat.com>,
	Laurent Pinchart <laurent.pinchart@skynet.be>
Subject: Re: [BUG] cdev_put() race condition
Date: Wed, 17 Dec 2008 20:30:32 +0100	[thread overview]
Message-ID: <200812172030.32535.hverkuil@xs4all.nl> (raw)
In-Reply-To: <20081217181645.GA26161@kroah.com>

On Wednesday 17 December 2008 19:16:45 Greg KH wrote:
> On Wed, Dec 17, 2008 at 02:37:33PM +0100, Hans Verkuil wrote:
> > > Again, don't use cdev's reference counting for your own object
> > > lifecycle, it is different and will cause problems, like you have
> > > found out.
> >
> > Sigh. It has nothing to do with how v4l uses it. And to demonstrate
> > this, here is how you reproduce it with the sg module (tested it with
> > my USB harddisk).
> >
> > 1) apply this patch to char_dev.c:
>
> <snip>
>
> Ok, since I can't convince you that using a cdev for your reference
> counting is incorrect, I'll have to go change the cdev code to prevent
> you from doing this :(

Erm, you haven't told me yet why it's a bad idea. You just said "don't do 
it", but I haven't seen the reason for it. There doesn't seem to be any 
documentation on how to properly use cdev besides the Kernel Device Drivers 
book, which (if memory serves) doesn't mention anything on this topic.

I really don't mind implementing refcounting in the v4l framework, I just 
want to understand why it should be done like that!

It seems to me that I will just be shadowing the refcounting of cdev if I 
implement refcounting in v4l: init to 1 on creation, increase on open, 
decrease on close, decrease on deletion. It's all terribly familiar...

> Anyway, do you have a patch for the cdev code to propose how to fix this
> issue you are having?

Sure, here it is:

--- fs/char_dev.c.orig	2008-12-17 20:28:40.000000000 +0100
+++ fs/char_dev.c	2008-12-17 20:28:49.000000000 +0100
@@ -345,7 +345,9 @@
 {
 	if (p) {
 		struct module *owner = p->owner;
+		spin_lock(&cdev_lock);
 		kobject_put(&p->kobj);
+		spin_unlock(&cdev_lock);
 		module_put(owner);
 	}
 }
@@ -415,14 +417,12 @@
 
 static void cdev_purge(struct cdev *cdev)
 {
-	spin_lock(&cdev_lock);
 	while (!list_empty(&cdev->list)) {
 		struct inode *inode;
 		inode = container_of(cdev->list.next, struct inode, i_devices);
 		list_del_init(&inode->i_devices);
 		inode->i_cdev = NULL;
 	}
-	spin_unlock(&cdev_lock);
 }
 
 /*
@@ -478,7 +478,9 @@
 void cdev_del(struct cdev *p)
 {
 	cdev_unmap(p->dev, p->count);
+	spin_lock(&cdev_lock);
 	kobject_put(&p->kobj);
+	spin_unlock(&cdev_lock);
 }

This solves this particular problem. But this will certainly break v4l as it 
is right now, since the spin_lock means that the kref's release cannot do 
any sleeps, which is possible in v4l. If we want to allow that in cdev, 
then the spinlock has to be replaced by a mutex. But I have the strong 
feeling that that's not going to happen :-)

Regards,

	Hans

-- 
Hans Verkuil - video4linux developer - sponsored by TANDBERG

WARNING: multiple messages have this Message-ID (diff)
From: Hans Verkuil <hverkuil@xs4all.nl>
To: Greg KH <greg@kroah.com>
Cc: v4l <video4linux-list@redhat.com>, linux-kernel@vger.kernel.org
Subject: Re: [BUG] cdev_put() race condition
Date: Wed, 17 Dec 2008 20:30:32 +0100	[thread overview]
Message-ID: <200812172030.32535.hverkuil@xs4all.nl> (raw)
In-Reply-To: <20081217181645.GA26161@kroah.com>

On Wednesday 17 December 2008 19:16:45 Greg KH wrote:
> On Wed, Dec 17, 2008 at 02:37:33PM +0100, Hans Verkuil wrote:
> > > Again, don't use cdev's reference counting for your own object
> > > lifecycle, it is different and will cause problems, like you have
> > > found out.
> >
> > Sigh. It has nothing to do with how v4l uses it. And to demonstrate
> > this, here is how you reproduce it with the sg module (tested it with
> > my USB harddisk).
> >
> > 1) apply this patch to char_dev.c:
>
> <snip>
>
> Ok, since I can't convince you that using a cdev for your reference
> counting is incorrect, I'll have to go change the cdev code to prevent
> you from doing this :(

Erm, you haven't told me yet why it's a bad idea. You just said "don't do 
it", but I haven't seen the reason for it. There doesn't seem to be any 
documentation on how to properly use cdev besides the Kernel Device Drivers 
book, which (if memory serves) doesn't mention anything on this topic.

I really don't mind implementing refcounting in the v4l framework, I just 
want to understand why it should be done like that!

It seems to me that I will just be shadowing the refcounting of cdev if I 
implement refcounting in v4l: init to 1 on creation, increase on open, 
decrease on close, decrease on deletion. It's all terribly familiar...

> Anyway, do you have a patch for the cdev code to propose how to fix this
> issue you are having?

Sure, here it is:

--- fs/char_dev.c.orig	2008-12-17 20:28:40.000000000 +0100
+++ fs/char_dev.c	2008-12-17 20:28:49.000000000 +0100
@@ -345,7 +345,9 @@
 {
 	if (p) {
 		struct module *owner = p->owner;
+		spin_lock(&cdev_lock);
 		kobject_put(&p->kobj);
+		spin_unlock(&cdev_lock);
 		module_put(owner);
 	}
 }
@@ -415,14 +417,12 @@
 
 static void cdev_purge(struct cdev *cdev)
 {
-	spin_lock(&cdev_lock);
 	while (!list_empty(&cdev->list)) {
 		struct inode *inode;
 		inode = container_of(cdev->list.next, struct inode, i_devices);
 		list_del_init(&inode->i_devices);
 		inode->i_cdev = NULL;
 	}
-	spin_unlock(&cdev_lock);
 }
 
 /*
@@ -478,7 +478,9 @@
 void cdev_del(struct cdev *p)
 {
 	cdev_unmap(p->dev, p->count);
+	spin_lock(&cdev_lock);
 	kobject_put(&p->kobj);
+	spin_unlock(&cdev_lock);
 }

This solves this particular problem. But this will certainly break v4l as it 
is right now, since the spin_lock means that the kref's release cannot do 
any sleeps, which is possible in v4l. If we want to allow that in cdev, 
then the spinlock has to be replaced by a mutex. But I have the strong 
feeling that that's not going to happen :-)

Regards,

	Hans

-- 
Hans Verkuil - video4linux developer - sponsored by TANDBERG

--
video4linux-list mailing list
Unsubscribe mailto:video4linux-list-request@redhat.com?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list

  parent reply	other threads:[~2008-12-17 19:31 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-12-08 20:56 [BUG] cdev_put() race condition Hans Verkuil
2008-12-08 20:56 ` Hans Verkuil
2008-12-16 10:06 ` Hans Verkuil
2008-12-16 10:06   ` Hans Verkuil
2008-12-16 20:22 ` Greg KH
2008-12-16 21:00   ` Hans Verkuil
2008-12-16 21:00     ` Hans Verkuil
2008-12-16 21:21     ` Greg KH
2008-12-16 23:23       ` Hans Verkuil
2008-12-16 23:23         ` Hans Verkuil
2008-12-16 23:30         ` Greg KH
2008-12-17 13:37           ` Hans Verkuil
2008-12-17 13:37             ` Hans Verkuil
2008-12-17 14:52             ` Boaz Harrosh
2008-12-17 15:07               ` Hans Verkuil
2008-12-17 15:07                 ` Hans Verkuil
2008-12-17 16:09                 ` Boaz Harrosh
2008-12-17 17:33                   ` Hans Verkuil
2008-12-17 17:33                     ` Hans Verkuil
2008-12-17 18:08                     ` Al Viro
2008-12-18  8:12                       ` Boaz Harrosh
2008-12-18  8:25                     ` Boaz Harrosh
2008-12-17 18:16             ` Greg KH
2008-12-17 19:27               ` Laurent Pinchart
2008-12-17 19:27                 ` Laurent Pinchart
2008-12-17 19:35                 ` Greg KH
2008-12-17 19:30               ` Hans Verkuil [this message]
2008-12-17 19:30                 ` Hans Verkuil
2008-12-17 19:38                 ` Greg KH
2008-12-17 19:39                 ` Hans Verkuil
2008-12-17 19:39                   ` Hans Verkuil
2008-12-17 19:53                   ` Greg KH
2008-12-17 20:18                     ` Hans Verkuil
2008-12-17 20:18                       ` Hans Verkuil
2008-12-17 20:52                       ` Greg KH

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=200812172030.32535.hverkuil@xs4all.nl \
    --to=hverkuil@xs4all.nl \
    --cc=greg@kroah.com \
    --cc=laurent.pinchart@skynet.be \
    --cc=linux-kernel@vger.kernel.org \
    --cc=video4linux-list@redhat.com \
    /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.