Commit e9b667a8 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

usb: usbtmc: Fix bug in pipe direction for control transfers

The syzbot fuzzer reported a minor bug in the usbtmc driver:

usb 5-1: BOGUS control dir, pipe 80001e80 doesn't match bRequestType 0
WARNING: CPU: 0 PID: 3813 at drivers/usb/core/urb.c:412
usb_submit_urb+0x13a5/0x1970 drivers/usb/core/urb.c:410
Modules linked in:
CPU: 0 PID: 3813 Comm: syz-executor122 Not tainted
5.17.0-rc5-syzkaller-00306-g2293be58 #0
...
Call Trace:
 <TASK>
 usb_start_wait_urb+0x113/0x530 drivers/usb/core/message.c:58
 usb_internal_control_msg drivers/usb/core/message.c:102 [inline]
 usb_control_msg+0x2a5/0x4b0 drivers/usb/core/message.c:153
 usbtmc_ioctl_request drivers/usb/class/usbtmc.c:1947 [inline]

The problem is that usbtmc_ioctl_request() uses usb_rcvctrlpipe() for
all of its transfers, whether they are in or out.  It's easy to fix.

CC: <stable@vger.kernel.org>
Reported-and-tested-by: syzbot+a48e3d1a875240cab5de@syzkaller.appspotmail.com
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Link: https://lore.kernel.org/r/YiEsYTPEE6lOCOA5@rowland.harvard.eduSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 23907106
...@@ -1919,6 +1919,7 @@ static int usbtmc_ioctl_request(struct usbtmc_device_data *data, ...@@ -1919,6 +1919,7 @@ static int usbtmc_ioctl_request(struct usbtmc_device_data *data,
struct usbtmc_ctrlrequest request; struct usbtmc_ctrlrequest request;
u8 *buffer = NULL; u8 *buffer = NULL;
int rv; int rv;
unsigned int is_in, pipe;
unsigned long res; unsigned long res;
res = copy_from_user(&request, arg, sizeof(struct usbtmc_ctrlrequest)); res = copy_from_user(&request, arg, sizeof(struct usbtmc_ctrlrequest));
...@@ -1928,12 +1929,14 @@ static int usbtmc_ioctl_request(struct usbtmc_device_data *data, ...@@ -1928,12 +1929,14 @@ static int usbtmc_ioctl_request(struct usbtmc_device_data *data,
if (request.req.wLength > USBTMC_BUFSIZE) if (request.req.wLength > USBTMC_BUFSIZE)
return -EMSGSIZE; return -EMSGSIZE;
is_in = request.req.bRequestType & USB_DIR_IN;
if (request.req.wLength) { if (request.req.wLength) {
buffer = kmalloc(request.req.wLength, GFP_KERNEL); buffer = kmalloc(request.req.wLength, GFP_KERNEL);
if (!buffer) if (!buffer)
return -ENOMEM; return -ENOMEM;
if ((request.req.bRequestType & USB_DIR_IN) == 0) { if (!is_in) {
/* Send control data to device */ /* Send control data to device */
res = copy_from_user(buffer, request.data, res = copy_from_user(buffer, request.data,
request.req.wLength); request.req.wLength);
...@@ -1944,8 +1947,12 @@ static int usbtmc_ioctl_request(struct usbtmc_device_data *data, ...@@ -1944,8 +1947,12 @@ static int usbtmc_ioctl_request(struct usbtmc_device_data *data,
} }
} }
if (is_in)
pipe = usb_rcvctrlpipe(data->usb_dev, 0);
else
pipe = usb_sndctrlpipe(data->usb_dev, 0);
rv = usb_control_msg(data->usb_dev, rv = usb_control_msg(data->usb_dev,
usb_rcvctrlpipe(data->usb_dev, 0), pipe,
request.req.bRequest, request.req.bRequest,
request.req.bRequestType, request.req.bRequestType,
request.req.wValue, request.req.wValue,
...@@ -1957,7 +1964,7 @@ static int usbtmc_ioctl_request(struct usbtmc_device_data *data, ...@@ -1957,7 +1964,7 @@ static int usbtmc_ioctl_request(struct usbtmc_device_data *data,
goto exit; goto exit;
} }
if (rv && (request.req.bRequestType & USB_DIR_IN)) { if (rv && is_in) {
/* Read control data from device */ /* Read control data from device */
res = copy_to_user(request.data, buffer, rv); res = copy_to_user(request.data, buffer, rv);
if (res) if (res)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment