All of lore.kernel.org
 help / color / mirror / Atom feed
From: Boaz Harrosh <bharrosh@panasas.com>
To: Hans Verkuil <hverkuil@xs4all.nl>
Cc: Greg KH <greg@kroah.com>,
	linux-kernel@vger.kernel.org, v4l <video4linux-list@redhat.com>,
	Laurent Pinchart <laurent.pinchart@skynet.be>,
	Tejun Heo <tj@kernel.org>
Subject: Re: [BUG] cdev_put() race condition
Date: Thu, 18 Dec 2008 10:25:46 +0200	[thread overview]
Message-ID: <494A090A.30107@panasas.com> (raw)
In-Reply-To: <200812171833.39735.hverkuil@xs4all.nl>

Hans Verkuil wrote:
>>>>> delayin
>>>>> delayout
>>>>> delayout
>> OK Now I do not understand something. How is the double release possible?
>> I guess it is something to do with the complicated chrdev_open() in its
>> inode->i_cdev == NULL case. But still isn't the kref inside kobject
>> suppose to protect me from exactly that?
> 
> Only if there is also proper locking to prevent a kref_get from being called 
> when the release of a kref_put is in progress. And that's missing in cdev.
> 
> Typical scenario: a USB device is disconnected, the driver sees that no 
> applications are using it, then it calls cdev_del. This calls cdev_put, the 
> cdev's refcount goes to 0 and it will call release. BUT, at this moment an 
> application can open the device *again* and chrdev_open() will reuse the 
> i_cdev pointer and call cdev_get(p) on it, and this increases the refcount 
> from 0 to 1 again. And later it calls cdev_put again and release is called 
> a second time.

OK I see. 

> 
>>>>> Note the duplicate 'delayin' messages. Also note that the cdev struct
>>>>> was allocated by sg.c, so the second cdev cleanup will likely poke
>>>>> into already freed memory.
>>>>>

>> I had a similar problem and solved it in a way that I think should be
>> safe. I'll try and run your tests to make sure. Here is a short
>> description of my solution:
>>
>> MyDevice {
>>    ...
>>    embed_cdev;
>>    embed_kref;
>>    ...
>> };
>>
>> OnHotPlug() {
>> 	...
>> 	kref_init(embed_kref); // kref==1
>> 	cdev_add(embed_cdev);  // cdev==1
>> 	get_(embed_cdev);      // cdev++==2
>> }
>>
>> OnFileOpen() { // kernel does // cdev++==n > 2
>> 	kref_get(embed_kref); // kref++==n > 1
>> }
>>
>> OnFileClose() {
>> 	kref_put(embed_kref, __release); // kref++==n >= 0
>> } // kernel does // cdev--==n >= 1
>>
>> OnHotRemove() {
>> 	cdev_del(embed_cdev);  // cdev--==1
>> 	kref_put(embed_kref, __release); // kref--==n >= 0
>> }
>>
>> __release() { // by definition kref==0
>> 	put_(embed_cdev);      // cdev--==0
>> }
>>
>> What do you think?
> 
> This won't help either. __release calls cdev_put, the cdev refcount goes to 
> 0, the cdev release is called, but at this time someone can open the device 
> again. Refcounting in the driver simply won't help since chrdev_open is 
> always called before the driver has a chance to check anything.
> 

No, But at this point cdev_del has already been called before the final put,
so if a chrdev_open is called while in cdev_release it will not find my
device anymore. I have separated the unmapping of the device from it's final put.

> In addition, I think it is nuts to introduce a kref that just shadows the 
> cdev's kref. We should be able to rely on cdev for this.
> 

I agree, that's why I like Tejun's patch because in theory we can get
rid of the shadow kref. (Without a layering violation)

> I expect that when you test your driver with this you should hit the same 
> race condition. Remember that you need to mknod the device. If you rely on 
> udev then this will never happen because udev has removed the device node 
> before cdev_del is called. (At least, I think that is always true. I'm no 
> expert on this.)
> 

OK I see, I do use udev in all my fedora images. I will try to disable it
and test. So far I was unable to reproduce the problem with my device.

>> BTW sg does not use kref and I suspect it might be racy by its own.
> 
> It might, but it has nothing to do with this bug.
> 
> Regards,
> 
> 	Hans
> 

Thanks
Boaz

  parent reply	other threads:[~2008-12-18  8:26 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 [this message]
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
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=494A090A.30107@panasas.com \
    --to=bharrosh@panasas.com \
    --cc=greg@kroah.com \
    --cc=hverkuil@xs4all.nl \
    --cc=laurent.pinchart@skynet.be \
    --cc=linux-kernel@vger.kernel.org \
    --cc=tj@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.