Skip to content

Commit

Permalink
HID: usbhid: free raw_report buffers in usbhid_stop
Browse files Browse the repository at this point in the history
commit f7744fa upstream.

Free the unsent raw_report buffers when the device is removed.

Fixes a memory leak reported by syzbot at:
https://syzkaller.appspot.com/bug?id=7b4fa7cb1a7c2d3342a2a8a6c53371c8c418ab47

Reported-by: syzbot+47b26cd837ececfc666d@syzkaller.appspotmail.com
Tested-by: syzbot+47b26cd837ececfc666d@syzkaller.appspotmail.com
Signed-off-by: Anirudh Rayabharam <mail@anirudhrb.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
anirudhrb authored and gregkh committed Oct 7, 2021
1 parent 24f3fc9 commit 2b70486
Showing 1 changed file with 12 additions and 1 deletion.
13 changes: 12 additions & 1 deletion drivers/hid/usbhid/hid-core.c
Expand Up @@ -505,7 +505,7 @@ static void hid_ctrl(struct urb *urb)

if (unplug) {
usbhid->ctrltail = usbhid->ctrlhead;
} else {
} else if (usbhid->ctrlhead != usbhid->ctrltail) {
usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);

if (usbhid->ctrlhead != usbhid->ctrltail &&
Expand Down Expand Up @@ -1223,9 +1223,20 @@ static void usbhid_stop(struct hid_device *hid)
mutex_lock(&usbhid->mutex);

clear_bit(HID_STARTED, &usbhid->iofl);

spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */
set_bit(HID_DISCONNECTED, &usbhid->iofl);
while (usbhid->ctrltail != usbhid->ctrlhead) {
if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_OUT) {
kfree(usbhid->ctrl[usbhid->ctrltail].raw_report);
usbhid->ctrl[usbhid->ctrltail].raw_report = NULL;
}

usbhid->ctrltail = (usbhid->ctrltail + 1) &
(HID_CONTROL_FIFO_SIZE - 1);
}
spin_unlock_irq(&usbhid->lock);

usb_kill_urb(usbhid->urbin);
usb_kill_urb(usbhid->urbout);
usb_kill_urb(usbhid->urbctrl);
Expand Down

0 comments on commit 2b70486

Please sign in to comment.