| From 32a0721c6620b77504916dac0cea8ad497c4878a Mon Sep 17 00:00:00 2001 |
| From: Alan Stern <stern@rowland.harvard.edu> |
| Date: Tue, 17 Sep 2019 12:47:23 -0400 |
| Subject: USB: yurex: Don't retry on unexpected errors |
| |
| From: Alan Stern <stern@rowland.harvard.edu> |
| |
| commit 32a0721c6620b77504916dac0cea8ad497c4878a upstream. |
| |
| According to Greg KH, it has been generally agreed that when a USB |
| driver encounters an unknown error (or one it can't handle directly), |
| it should just give up instead of going into a potentially infinite |
| retry loop. |
| |
| The three codes -EPROTO, -EILSEQ, and -ETIME fall into this category. |
| They can be caused by bus errors such as packet loss or corruption, |
| attempting to communicate with a disconnected device, or by malicious |
| firmware. Nowadays the extent of packet loss or corruption is |
| negligible, so it should be safe for a driver to give up whenever one |
| of these errors occurs. |
| |
| Although the yurex driver handles -EILSEQ errors in this way, it |
| doesn't do the same for -EPROTO (as discovered by the syzbot fuzzer) |
| or other unrecognized errors. This patch adjusts the driver so that |
| it doesn't log an error message for -EPROTO or -ETIME, and it doesn't |
| retry after any errors. |
| |
| Reported-and-tested-by: syzbot+b24d736f18a1541ad550@syzkaller.appspotmail.com |
| Signed-off-by: Alan Stern <stern@rowland.harvard.edu> |
| CC: Tomoki Sekiyama <tomoki.sekiyama@gmail.com> |
| CC: <stable@vger.kernel.org> |
| Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.1909171245410.1590-100000@iolanthe.rowland.org |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/misc/yurex.c | 7 ++++--- |
| 1 file changed, 4 insertions(+), 3 deletions(-) |
| |
| --- a/drivers/usb/misc/yurex.c |
| +++ b/drivers/usb/misc/yurex.c |
| @@ -136,6 +136,7 @@ static void yurex_interrupt(struct urb * |
| switch (status) { |
| case 0: /*success*/ |
| break; |
| + /* The device is terminated or messed up, give up */ |
| case -EOVERFLOW: |
| dev_err(&dev->interface->dev, |
| "%s - overflow with length %d, actual length is %d\n", |
| @@ -144,12 +145,13 @@ static void yurex_interrupt(struct urb * |
| case -ENOENT: |
| case -ESHUTDOWN: |
| case -EILSEQ: |
| - /* The device is terminated, clean up */ |
| + case -EPROTO: |
| + case -ETIME: |
| return; |
| default: |
| dev_err(&dev->interface->dev, |
| "%s - unknown status received: %d\n", __func__, status); |
| - goto exit; |
| + return; |
| } |
| |
| /* handle received message */ |
| @@ -181,7 +183,6 @@ static void yurex_interrupt(struct urb * |
| break; |
| } |
| |
| -exit: |
| retval = usb_submit_urb(dev->urb, GFP_ATOMIC); |
| if (retval) { |
| dev_err(&dev->interface->dev, "%s - usb_submit_urb failed: %d\n", |