#syz test: https://github.com/google/kasan.git e96407b4 >From d3d9edf17e33889e0fc4238f3d03a2dce7af30e1 Mon Sep 17 00:00:00 2001 From: Oliver Neukum <oneukum@xxxxxxxx> Date: Tue, 19 Nov 2019 14:09:41 +0100 Subject: [PATCH] cdc-wdm: add timeout in wdm_flush() wdm_flush() will wait forever for IO to end. If a device happens to crash exactly at that time and becomes unresponsive or turns rogue and malicious exactly at that time, we get unkillable tasks. The solition is to add a sensible timeout. Signed-off-by: Oliver Neukum <oneukum@xxxxxxxx> --- drivers/usb/class/cdc-wdm.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index f9f7c8a5e091..17de5c88a325 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -587,8 +587,9 @@ static ssize_t wdm_read static int wdm_flush(struct file *file, fl_owner_t id) { struct wdm_device *desc = file->private_data; + int timeout; - wait_event(desc->wait, + timeout = wait_event_timeout(desc->wait, /* * needs both flags. We cannot do with one * because resetting it would cause a race @@ -596,7 +597,14 @@ static int wdm_flush(struct file *file, fl_owner_t id) * a disconnect */ !test_bit(WDM_IN_USE, &desc->flags) || - test_bit(WDM_DISCONNECTING, &desc->flags)); + test_bit(WDM_DISCONNECTING, &desc->flags), + /* pulled out of thin air */ + 30 * HZ); + + if (!timeout) { + usb_kill_urb(desc->command); + return -EIO; + } /* cannot dereference desc->intf if WDM_DISCONNECTING */ if (test_bit(WDM_DISCONNECTING, &desc->flags)) -- 2.16.4