On Mon, 23 Jun 2003, Oliver Neukum wrote:

>> >> If usb_disconnect() can happen while already executing in open(), and if
>> >> the former frees the data structures used by the driver, then the latter
>> >> call might continue working with already freed memory region which could
>> >> lead to catastrophe.

>Exactly. Very good. Therefore you must never free [in usb_disconnect() -tt]
>the lock and that piece of data (usually a pointer to a device descriptor)

Thank you very much. These were the magic words I wanted to hear. So the
solution is to use _static_ lock.

>Many examples can be found in the kernel sources.

Right. So let's look at drivers/usb/ov511.c (2.4.21).

--<clip>--
ov51x_v4l1_open(struct inode *inode, struct file *file)
{
        struct video_device *vdev = video_devdata(file);
        struct usb_ov511 *ov = vdev->priv;
        int err, i;

        PDEBUG(4, "opening");

        down(&ov->lock);
--<clip>--

ov->lock is taken unconditionally, thus ov _must not freed in
usb_disconnect()_! And what do we see in usb_disconnect?

--<clip>--
ov51x_disconnect(struct usb_device *dev, void *ptr)
{
        struct usb_ov511 *ov = (struct usb_ov511 *) ptr;
        int n;

        MOD_INC_USE_COUNT;

        video_unregister_device(&ov->vdev);

        /* Free the memory */
        if (ov && !ov->user) {
                down(&ov->cbuf_lock);
                kfree(ov->cbuf);
                ov->cbuf = NULL;
                up(&ov->cbuf_lock);

                ov51x_dealloc(ov, 1);
                kfree(ov);
                ov = NULL;
        }
        MOD_DEC_USE_COUNT;
}
--<clip>--

I deleted some (hopefully) irrelevant lines to make the example smaller
(so you may want to look at the original code). Looks exactly the same bug
that in the driver I'm maintaining (qc-usb) which isn't surpising
considering they are probably derived from same original code (CPiA?).

Another danger sign: video_unregister_device() is potentially called while
executing the open() function called from videodev.c. I don't know if this
is allowed (I should go asking from V4L list, I guess).

ov51 was actually the second driver I looked, the first one was the Philips
driver pwc. There I see:

--<clip>--
static void usb_pwc_disconnect(struct usb_device *udev, void *ptr)
{
        struct pwc_device *pdev;
        int hint;
        DECLARE_WAITQUEUE(wait, current);

        lock_kernel();
        free_mem_leak();
--<clip>--

Does taking lock_kernel() prevent usb_disconnect() executing simultaneously
with the open() call (the code doesn't specifically take lock_kernel() in
open() call, but maybe kernel does that automatically)? If so, pwc should
be safe. But I don't know.

>> And wasn't it Linus not God... oh nevermind. I just remembered the
>> principle of equivalence ;)
>Blessed be he and all code that floweth from him.

Hallelujah!


-------------------------------------------------------
This SF.Net email is sponsored by: INetU
Attention Web Developers & Consultants: Become An INetU Hosting Partner.
Refer Dedicated Servers. We Manage Them. You Get 10% Monthly Commission!
INetU Dedicated Managed Hosting http://www.inetu.net/partner/index.php
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to