]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-4.14/usb-gadget-f_hid-fix-deadlock-in-f_hidg_write.patch
4.14-stable patches
[thirdparty/kernel/stable-queue.git] / queue-4.14 / usb-gadget-f_hid-fix-deadlock-in-f_hidg_write.patch
1 From 072684e8c58d17e853f8e8b9f6d9ce2e58d2b036 Mon Sep 17 00:00:00 2001
2 From: Radoslav Gerganov <rgerganov@vmware.com>
3 Date: Tue, 5 Mar 2019 10:10:34 +0000
4 Subject: USB: gadget: f_hid: fix deadlock in f_hidg_write()
5
6 From: Radoslav Gerganov <rgerganov@vmware.com>
7
8 commit 072684e8c58d17e853f8e8b9f6d9ce2e58d2b036 upstream.
9
10 In f_hidg_write() the write_spinlock is acquired before calling
11 usb_ep_queue() which causes a deadlock when dummy_hcd is being used.
12 This is because dummy_queue() callbacks into f_hidg_req_complete() which
13 tries to acquire the same spinlock. This is (part of) the backtrace when
14 the deadlock occurs:
15
16 0xffffffffc06b1410 in f_hidg_req_complete
17 0xffffffffc06a590a in usb_gadget_giveback_request
18 0xffffffffc06cfff2 in dummy_queue
19 0xffffffffc06a4b96 in usb_ep_queue
20 0xffffffffc06b1eb6 in f_hidg_write
21 0xffffffff8127730b in __vfs_write
22 0xffffffff812774d1 in vfs_write
23 0xffffffff81277725 in SYSC_write
24
25 Fix this by releasing the write_spinlock before calling usb_ep_queue()
26
27 Reviewed-by: James Bottomley <James.Bottomley@HansenPartnership.com>
28 Tested-by: James Bottomley <James.Bottomley@HansenPartnership.com>
29 Cc: stable@vger.kernel.org # 4.11+
30 Fixes: 749494b6bdbb ("usb: gadget: f_hid: fix: Move IN request allocation to set_alt()")
31 Signed-off-by: Radoslav Gerganov <rgerganov@vmware.com>
32 Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
33 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
34
35 ---
36 drivers/usb/gadget/function/f_hid.c | 6 +++---
37 1 file changed, 3 insertions(+), 3 deletions(-)
38
39 --- a/drivers/usb/gadget/function/f_hid.c
40 +++ b/drivers/usb/gadget/function/f_hid.c
41 @@ -395,20 +395,20 @@ try_again:
42 req->complete = f_hidg_req_complete;
43 req->context = hidg;
44
45 + spin_unlock_irqrestore(&hidg->write_spinlock, flags);
46 +
47 status = usb_ep_queue(hidg->in_ep, req, GFP_ATOMIC);
48 if (status < 0) {
49 ERROR(hidg->func.config->cdev,
50 "usb_ep_queue error on int endpoint %zd\n", status);
51 - goto release_write_pending_unlocked;
52 + goto release_write_pending;
53 } else {
54 status = count;
55 }
56 - spin_unlock_irqrestore(&hidg->write_spinlock, flags);
57
58 return status;
59 release_write_pending:
60 spin_lock_irqsave(&hidg->write_spinlock, flags);
61 -release_write_pending_unlocked:
62 hidg->write_pending = 0;
63 spin_unlock_irqrestore(&hidg->write_spinlock, flags);
64