Skip to content

Commit 072684e

Browse files
Radoslav GerganovFelipe Balbi
authored andcommitted
USB: gadget: f_hid: fix deadlock in f_hidg_write()
In f_hidg_write() the write_spinlock is acquired before calling usb_ep_queue() which causes a deadlock when dummy_hcd is being used. This is because dummy_queue() callbacks into f_hidg_req_complete() which tries to acquire the same spinlock. This is (part of) the backtrace when the deadlock occurs: 0xffffffffc06b1410 in f_hidg_req_complete 0xffffffffc06a590a in usb_gadget_giveback_request 0xffffffffc06cfff2 in dummy_queue 0xffffffffc06a4b96 in usb_ep_queue 0xffffffffc06b1eb6 in f_hidg_write 0xffffffff8127730b in __vfs_write 0xffffffff812774d1 in vfs_write 0xffffffff81277725 in SYSC_write Fix this by releasing the write_spinlock before calling usb_ep_queue() Reviewed-by: James Bottomley <James.Bottomley@HansenPartnership.com> Tested-by: James Bottomley <James.Bottomley@HansenPartnership.com> Cc: stable@vger.kernel.org # 4.11+ Fixes: 749494b ("usb: gadget: f_hid: fix: Move IN request allocation to set_alt()") Signed-off-by: Radoslav Gerganov <rgerganov@vmware.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
1 parent 091dacc commit 072684e

File tree

1 file changed

+3
-3
lines changed

1 file changed

+3
-3
lines changed

drivers/usb/gadget/function/f_hid.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -391,20 +391,20 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer,
391391
req->complete = f_hidg_req_complete;
392392
req->context = hidg;
393393

394+
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
395+
394396
status = usb_ep_queue(hidg->in_ep, req, GFP_ATOMIC);
395397
if (status < 0) {
396398
ERROR(hidg->func.config->cdev,
397399
"usb_ep_queue error on int endpoint %zd\n", status);
398-
goto release_write_pending_unlocked;
400+
goto release_write_pending;
399401
} else {
400402
status = count;
401403
}
402-
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
403404

404405
return status;
405406
release_write_pending:
406407
spin_lock_irqsave(&hidg->write_spinlock, flags);
407-
release_write_pending_unlocked:
408408
hidg->write_pending = 0;
409409
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
410410

0 commit comments

Comments
 (0)