summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2021-07-12 14:54:36 -0400
committerSasha Levin <sashal@kernel.org>2021-08-26 08:35:34 -0400
commitd4930271a4096769c43eb103aaf7d3a043ae138e (patch)
treeab9a3c41c83eba7ab209a03f2dfd85903a4571ea
parentba6c1b004ac5aaee418ce84acbecdc4d89a67bbe (diff)
USB: core: Fix incorrect pipe calculation in do_proc_control()
[ Upstream commit b0863f1927323110e3d0d69f6adb6a91018a9a3c ] When the user submits a control URB via usbfs, the user supplies the bRequestType value and the kernel uses it to compute the pipe value. However, do_proc_control() performs this computation incorrectly in the case where the bRequestType direction bit is set to USB_DIR_IN and the URB's transfer length is 0: The pipe's direction is also set to IN but it should be OUT, which is the direction the actual transfer will use regardless of bRequestType. Commit 5cc59c418fde ("USB: core: WARN if pipe direction != setup packet direction") added a check to compare the direction bit in the pipe value to a control URB's actual direction and to WARN if they are different. This can be triggered by the incorrect computation mentioned above, as found by syzbot. This patch fixes the computation, thus avoiding the WARNing. Reported-and-tested-by: syzbot+72af3105289dcb4c055b@syzkaller.appspotmail.com Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Link: https://lore.kernel.org/r/20210712185436.GB326369@rowland.harvard.edu Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/usb/core/devio.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 2218941d35a3f..73b60f013b205 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1133,7 +1133,7 @@ static int do_proc_control(struct usb_dev_state *ps,
"wIndex=%04x wLength=%04x\n",
ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,
ctrl->wIndex, ctrl->wLength);
- if (ctrl->bRequestType & 0x80) {
+ if ((ctrl->bRequestType & USB_DIR_IN) && ctrl->wLength) {
pipe = usb_rcvctrlpipe(dev, 0);
snoop_urb(dev, NULL, pipe, ctrl->wLength, tmo, SUBMIT, NULL, 0);