All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ming Lei <ming.lei@canonical.com>
To: Oliver Neukum <oneukum@suse.de>
Cc: Alan Stern <stern@rowland.harvard.edu>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Jiri Kosina <jkosina@suse.cz>,
	linux-usb@vger.kernel.org, linux-input@vger.kernel.org,
	stable@vger.kernel.org
Subject: Re: [PATCH] hid: usbhid: fix possible deadlock in __usbhid_submit_report
Date: Wed, 25 Apr 2012 17:14:19 +0800	[thread overview]
Message-ID: <CACVXFVM6KMeMcXy549x9XqhqvCzq73pXvhLki363=KjQu2Nfsg@mail.gmail.com> (raw)
In-Reply-To: <201204251006.16272.oneukum@suse.de>

On Wed, Apr 25, 2012 at 4:06 PM, Oliver Neukum <oneukum@suse.de> wrote:

>
> Indeed. Upon further thought it seems to me that we need to prevent
> resubmission and all is well. And we almost have all the infrastructure.
>
> So how about this, making it more reusable:

Yes, this one is good, better than the adding lock.

>
> From ce77d793252d1abf3a0ec6c67e4a7a05ac6d846a Mon Sep 17 00:00:00 2001
> From: Oliver Neukum <oliver@neukum.org>
> Date: Wed, 25 Apr 2012 09:54:00 +0200
> Subject: [PATCH] usbhid: prevent deadlock during timeout
>
> On some HCDs usb_unlink_urb() can directly call the
> completion handler. That limits the spinlocks that can
> be taken in the handler to locks not held while calling
> usb_unlink_urb()
> To prevent a race with resubmission, this patch exposes
> usbcore's infrastructure for blocking submission, uses it
> and so drops the lock without causing a race in usbhid.
>
> Signed-off-by: Oliver Neukum <oneukum@suse.de>
> ---
>  drivers/hid/usbhid/hid-core.c |   38 ++++++++++++++++++++++++++++++++++----
>  drivers/usb/core/urb.c        |   30 ++++++++++++++++++++++++++++++
>  include/linux/usb.h           |    2 ++
>  3 files changed, 66 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
> index 5bf91db..763257d 100644
> --- a/drivers/hid/usbhid/hid-core.c
> +++ b/drivers/hid/usbhid/hid-core.c
> @@ -535,11 +535,27 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
>                         * the queue is known to run
>                         * but an earlier request may be stuck
>                         * we may need to time out
> -                        * no race because this is called under
> +                        * no race because the URB is blocked under
>                         * spinlock
>                         */
> -                       if (time_after(jiffies, usbhid->last_out + HZ * 5))
> +                       if (time_after(jiffies, usbhid->last_out + HZ * 5)) {
> +                               usb_block_urb(usbhid->urbout);
> +                               /* drop lock to not deadlock if the callback is called */
> +                               spin_unlock(&usbhid->lock);
>                                usb_unlink_urb(usbhid->urbout);
> +                               spin_lock(&usbhid->lock);
> +                               usb_unblock_urb(usbhid->urbout);
> +                               /*
> +                                * if the unlinking has already completed
> +                                * the pump will have been stopped
> +                                * it must be restarted now
> +                                */
> +                               if (!test_bit(HID_OUT_RUNNING, &usbhid->iofl))
> +                                       if (!hid_submit_out(hid))

You need to add check of "usbhid->outtail != usbhid->outhead" above.

> +                                               set_bit(HID_OUT_RUNNING, &usbhid->iofl);
> +
> +
> +                       }
>                }
>                return;
>        }
> @@ -583,11 +599,25 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
>                 * the queue is known to run
>                 * but an earlier request may be stuck
>                 * we may need to time out
> -                * no race because this is called under
> +                * no race because the URB is blocked under
>                 * spinlock
>                 */
> -               if (time_after(jiffies, usbhid->last_ctrl + HZ * 5))
> +               if (time_after(jiffies, usbhid->last_ctrl + HZ * 5)) {
> +                       usb_block_urb(usbhid->urbctrl);
> +                       /* drop lock to not deadlock if the callback is called */
> +                       spin_unlock(&usbhid->lock);
>                        usb_unlink_urb(usbhid->urbctrl);
> +                       spin_lock(&usbhid->lock);
> +                       usb_unblock_urb(usbhid->urbctrl);
> +                       /*
> +                        * if the unlinking has already completed
> +                        * the pump will have been stopped
> +                        * it must be restarted now
> +                        */
> +                       if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl))
> +                               if (!hid_submit_ctrl(hid))

Similar as above.

> +                                       set_bit(HID_CTRL_RUNNING, &usbhid->iofl);
> +               }
>        }
>  }
>
> diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
> index cd9b3a2..1d1b010 100644
> --- a/drivers/usb/core/urb.c
> +++ b/drivers/usb/core/urb.c
> @@ -681,6 +681,36 @@ void usb_unpoison_urb(struct urb *urb)
>  EXPORT_SYMBOL_GPL(usb_unpoison_urb);
>
>  /**
> + * usb_block_urb - reliably prevent further use of an URB
> + * @urb: pointer to URB to be blocked, may be NULL
> + *
> + * After the routine has run, attempts to resubmit the URB will fail
> + * with error -EPERM.  Thus even if the URB's completion handler always
> + * tries to resubmit, it will not succeed and the URB will become idle.
> + *
> + * The URB must not be deallocated while this routine is running.  In
> + * particular, when a driver calls this routine, it must insure that the
> + * completion handler cannot deallocate the URB.
> + */
> +void usb_block_urb(struct urb *urb)
> +{
> +        if (!urb)
> +                return;
> +
> +        atomic_inc(&urb->reject);
> +}
> +EXPORT_SYMBOL_GPL(usb_block_urb);
> +
> +void usb_unblock_urb(struct urb *urb)
> +{
> +        if (!urb)
> +                return;
> +
> +        atomic_dec(&urb->reject);
> +}
> +EXPORT_SYMBOL_GPL(usb_unblock_urb);
> +
> +/**
>  * usb_kill_anchored_urbs - cancel transfer requests en masse
>  * @anchor: anchor the requests are bound to
>  *
> diff --git a/include/linux/usb.h b/include/linux/usb.h
> index 73b68d1..23df8ae 100644
> --- a/include/linux/usb.h
> +++ b/include/linux/usb.h
> @@ -1379,6 +1379,8 @@ extern int usb_unlink_urb(struct urb *urb);
>  extern void usb_kill_urb(struct urb *urb);
>  extern void usb_poison_urb(struct urb *urb);
>  extern void usb_unpoison_urb(struct urb *urb);
> +extern void usb_block_urb(struct urb *urb);
> +extern void usb_unblock_urb(struct urb *urb);
>  extern void usb_kill_anchored_urbs(struct usb_anchor *anchor);
>  extern void usb_poison_anchored_urbs(struct usb_anchor *anchor);
>  extern void usb_unpoison_anchored_urbs(struct usb_anchor *anchor);


Thanks,
--
Ming Lei
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

  reply	other threads:[~2012-04-25  9:14 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-04-19 13:51 [PATCH] hid: usbhid: fix possible deadlock in __usbhid_submit_report Ming Lei
     [not found] ` <1334843464-1585-1-git-send-email-ming.lei-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
2012-04-19 16:11   ` Oliver Neukum
2012-04-20  2:10     ` Ming Lei
2012-04-20  7:57       ` Oliver Neukum
     [not found]         ` <201204200957.34154.oneukum-l3A5Bk7waGM@public.gmane.org>
2012-04-20 10:17           ` Ming Lei
2012-04-20 10:45             ` Oliver Neukum
2012-04-20 12:53               ` Ming Lei
2012-04-20 14:07                 ` Oliver Neukum
     [not found]               ` <201204201245.44981.oneukum-l3A5Bk7waGM@public.gmane.org>
2012-04-20 13:30                 ` Ming Lei
2012-04-21  0:37                 ` Alan Stern
     [not found]                   ` <Pine.LNX.4.44L0.1204202032530.19313-100000-pYrvlCTfrz9XsRXLowluHWD2FQJk+8+b@public.gmane.org>
2012-04-21 10:25                     ` Oliver Neukum
2012-04-21 13:40                       ` Ming Lei
2012-04-21 17:31                         ` Alan Stern
     [not found]                           ` <Pine.LNX.4.44L0.1204211327090.475-100000-pYrvlCTfrz9XsRXLowluHWD2FQJk+8+b@public.gmane.org>
2012-04-21 19:28                             ` Oliver Neukum
2012-04-21 21:49                               ` Alan Stern
     [not found]                                 ` <Pine.LNX.4.44L0.1204211717310.3981-100000-pYrvlCTfrz9XsRXLowluHWD2FQJk+8+b@public.gmane.org>
2012-04-22 10:51                                   ` Ming Lei
2012-04-22 12:50                                     ` Alan Stern
2012-04-22 13:52                                       ` Ming Lei
2012-04-23 15:42                                         ` Alan Stern
2012-04-24  4:19                                           ` Ming Lei
2012-04-24 14:22                                             ` Oliver Neukum
2012-04-24 15:46                                               ` Ming Lei
2012-04-24 18:57                                                 ` Oliver Neukum
2012-04-25  1:27                                                   ` Ming Lei
2012-04-25  6:19                                                     ` Oliver Neukum
2012-04-25  6:32                                                       ` Oliver Neukum
2012-04-25  7:02                                                       ` Ming Lei
     [not found]                                                         ` <CACVXFVMEttnWo34ZxBsm4vdW1y5f5mBjY1s6BVbbsjck-4cSbA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2012-04-25  8:08                                                           ` Oliver Neukum
     [not found]                                             ` <CACVXFVNhPKbFZN5AjT3BNdNP+3bZP7miJZrBEER97scMR5nNAQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2012-04-24 15:20                                               ` Alan Stern
     [not found]                                                 ` <Pine.LNX.4.44L0.1204241110160.1511-100000-IYeN2dnnYyZXsRXLowluHWD2FQJk+8+b@public.gmane.org>
2012-04-25  0:27                                                   ` Ming Lei
     [not found]                                           ` <Pine.LNX.4.44L0.1204231121200.1612-100000-IYeN2dnnYyZXsRXLowluHWD2FQJk+8+b@public.gmane.org>
2012-04-24 14:35                                             ` Oliver Neukum
2012-04-24 15:10                                               ` Alan Stern
2012-04-25  8:06                                                 ` Oliver Neukum
2012-04-25  9:14                                                   ` Ming Lei [this message]
     [not found]                                                     ` <CACVXFVM6KMeMcXy549x9XqhqvCzq73pXvhLki363=KjQu2Nfsg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2012-04-25 10:52                                                       ` Oliver Neukum
2012-04-25 11:24                                                         ` Huajun Li
     [not found]                                                           ` <CA+v9cxYi-LC-gXMbP7J81ArCjwQJZQ=9ceu66W0QQe+6UD_LvQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2012-04-25 11:33                                                             ` Oliver Neukum
2012-04-25 13:18                                                         ` Ming Lei
     [not found]                                                         ` <201204251252.55901.oneukum-l3A5Bk7waGM@public.gmane.org>
2012-04-25 15:19                                                           ` Alan Stern
2012-04-26 22:44                                                             ` Jiri Kosina
2012-04-26 23:40                                                               ` Greg Kroah-Hartman
2012-04-23  8:21                                     ` Oliver Neukum
2012-04-22 11:53                           ` Ming Lei
2012-04-22 12:54                             ` Alan Stern
     [not found]                             ` <CACVXFVOQpYcHUj3XApyCVWDuvUEKi+RSWC8Ly4Dnj7vrun68cg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2012-04-23  8:24                               ` Oliver Neukum
     [not found]             ` <CACVXFVP42WL2aVDGSn0BF0NJbg824VsU=Fs30XKEif6siOrQvw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2012-04-20 21:59               ` Dmitry Torokhov
2012-04-21  1:06                 ` Ming Lei

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='CACVXFVM6KMeMcXy549x9XqhqvCzq73pXvhLki363=KjQu2Nfsg@mail.gmail.com' \
    --to=ming.lei@canonical.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=jkosina@suse.cz \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=oneukum@suse.de \
    --cc=stable@vger.kernel.org \
    --cc=stern@rowland.harvard.edu \
    /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.