diff options
author | Antti Palosaari <crope@iki.fi> | 2015-10-06 00:22:23 -0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-11-09 14:33:34 -0800 |
commit | f4778084b715e649d4b095151cfe30c9067c2a59 (patch) | |
tree | c4cd39193d6ed6c931b3006479dd3bee3ad6cc74 /drivers/media | |
parent | 76d6f9644b3c9029e920b315c7187605e7acf260 (diff) |
rtl28xxu: fix control message flaws
commit d18ca5b7ceca0e9674cb4bb2ed476b0fcbb23ba2 upstream.
Add lock to prevent concurrent access for control message as control
message function uses shared buffer. Without the lock there may be
remote control polling which messes the buffer causing IO errors.
Increase buffer size and add check for maximum supported message
length.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=103391
Fixes: c56222a6b25c ("[media] rtl28xxu: move usb buffers to state")
Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 15 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/rtl28xxu.h | 2 |
2 files changed, 14 insertions, 3 deletions
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 895441fe90f7..e862554952c1 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -34,6 +34,14 @@ static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req) unsigned int pipe; u8 requesttype; + mutex_lock(&d->usb_mutex); + + if (req->size > sizeof(dev->buf)) { + dev_err(&d->intf->dev, "too large message %u\n", req->size); + ret = -EINVAL; + goto err_mutex_unlock; + } + if (req->index & CMD_WR_FLAG) { /* write */ memcpy(dev->buf, req->data, req->size); @@ -50,14 +58,17 @@ static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req) dvb_usb_dbg_usb_control_msg(d->udev, 0, requesttype, req->value, req->index, dev->buf, req->size); if (ret < 0) - goto err; + goto err_mutex_unlock; /* read request, copy returned data to return buf */ if (requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) memcpy(req->data, dev->buf, req->size); + mutex_unlock(&d->usb_mutex); + return 0; -err: +err_mutex_unlock: + mutex_unlock(&d->usb_mutex); dev_dbg(&d->intf->dev, "failed=%d\n", ret); return ret; } diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h index 1b5d7ffb685e..1bdeda05d332 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h @@ -69,7 +69,7 @@ struct rtl28xxu_dev { - u8 buf[28]; + u8 buf[128]; u8 chip_id; u8 tuner; char *tuner_name; |