Commit 78469903 authored by Olivier Grenie's avatar Olivier Grenie Committed by Greg Kroah-Hartman

dib0700: protect the dib0700 buffer access

commit bff469f4 upstream.

This patch protects the common buffer access inside the dib0700 in order
to manage concurrent access. This protection is done using mutex.

Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
Cc: Florian Mickler <florian@mickler.org>
Signed-off-by: default avatarJavier Marcet <javier@marcet.info>
Signed-off-by: default avatarOlivier Grenie <olivier.grenie@dibcom.fr>
Signed-off-by: default avatarPatrick Boettcher <patrick.boettcher@dibcom.fr>
[mchehab@redhat.com: dprint requires 3 arguments. Replaced by dib_info]
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 4c505e95
...@@ -30,6 +30,11 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, ...@@ -30,6 +30,11 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
struct dib0700_state *st = d->priv; struct dib0700_state *st = d->priv;
int ret; int ret;
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
deb_info("could not acquire lock");
return 0;
}
ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
REQUEST_GET_VERSION, REQUEST_GET_VERSION,
USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
...@@ -46,6 +51,7 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, ...@@ -46,6 +51,7 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
if (fwtype != NULL) if (fwtype != NULL)
*fwtype = (st->buf[12] << 24) | (st->buf[13] << 16) | *fwtype = (st->buf[12] << 24) | (st->buf[13] << 16) |
(st->buf[14] << 8) | st->buf[15]; (st->buf[14] << 8) | st->buf[15];
mutex_unlock(&d->usb_mutex);
return ret; return ret;
} }
...@@ -108,7 +114,12 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen ...@@ -108,7 +114,12 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen
int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val) int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val)
{ {
struct dib0700_state *st = d->priv; struct dib0700_state *st = d->priv;
s16 ret; int ret;
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
deb_info("could not acquire lock");
return 0;
}
st->buf[0] = REQUEST_SET_GPIO; st->buf[0] = REQUEST_SET_GPIO;
st->buf[1] = gpio; st->buf[1] = gpio;
...@@ -116,6 +127,7 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_ ...@@ -116,6 +127,7 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_
ret = dib0700_ctrl_wr(d, st->buf, 3); ret = dib0700_ctrl_wr(d, st->buf, 3);
mutex_unlock(&d->usb_mutex);
return ret; return ret;
} }
...@@ -125,6 +137,11 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) ...@@ -125,6 +137,11 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
int ret; int ret;
if (st->fw_version >= 0x10201) { if (st->fw_version >= 0x10201) {
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
deb_info("could not acquire lock");
return 0;
}
st->buf[0] = REQUEST_SET_USB_XFER_LEN; st->buf[0] = REQUEST_SET_USB_XFER_LEN;
st->buf[1] = (nb_ts_packets >> 8) & 0xff; st->buf[1] = (nb_ts_packets >> 8) & 0xff;
st->buf[2] = nb_ts_packets & 0xff; st->buf[2] = nb_ts_packets & 0xff;
...@@ -132,6 +149,7 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) ...@@ -132,6 +149,7 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets); deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets);
ret = dib0700_ctrl_wr(d, st->buf, 3); ret = dib0700_ctrl_wr(d, st->buf, 3);
mutex_unlock(&d->usb_mutex);
} else { } else {
deb_info("this firmware does not allow to change the USB xfer len\n"); deb_info("this firmware does not allow to change the USB xfer len\n");
ret = -EIO; ret = -EIO;
...@@ -208,6 +226,10 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, ...@@ -208,6 +226,10 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
} else { } else {
/* Write request */ /* Write request */
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
deb_info("could not acquire lock");
return 0;
}
st->buf[0] = REQUEST_NEW_I2C_WRITE; st->buf[0] = REQUEST_NEW_I2C_WRITE;
st->buf[1] = msg[i].addr << 1; st->buf[1] = msg[i].addr << 1;
st->buf[2] = (en_start << 7) | (en_stop << 6) | st->buf[2] = (en_start << 7) | (en_stop << 6) |
...@@ -227,6 +249,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, ...@@ -227,6 +249,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
USB_TYPE_VENDOR | USB_DIR_OUT, USB_TYPE_VENDOR | USB_DIR_OUT,
0, 0, st->buf, msg[i].len + 4, 0, 0, st->buf, msg[i].len + 4,
USB_CTRL_GET_TIMEOUT); USB_CTRL_GET_TIMEOUT);
mutex_unlock(&d->usb_mutex);
if (result < 0) { if (result < 0) {
deb_info("i2c write error (status = %d)\n", result); deb_info("i2c write error (status = %d)\n", result);
break; break;
...@@ -249,6 +272,10 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, ...@@ -249,6 +272,10 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
if (mutex_lock_interruptible(&d->i2c_mutex) < 0) if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN; return -EAGAIN;
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
deb_info("could not acquire lock");
return 0;
}
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
/* fill in the address */ /* fill in the address */
...@@ -279,6 +306,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, ...@@ -279,6 +306,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
break; break;
} }
} }
mutex_unlock(&d->usb_mutex);
mutex_unlock(&d->i2c_mutex); mutex_unlock(&d->i2c_mutex);
return i; return i;
...@@ -337,7 +365,12 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, ...@@ -337,7 +365,12 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
u16 pll_loopdiv, u16 free_div, u16 dsuScaler) u16 pll_loopdiv, u16 free_div, u16 dsuScaler)
{ {
struct dib0700_state *st = d->priv; struct dib0700_state *st = d->priv;
s16 ret; int ret;
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
deb_info("could not acquire lock");
return 0;
}
st->buf[0] = REQUEST_SET_CLOCK; st->buf[0] = REQUEST_SET_CLOCK;
st->buf[1] = (en_pll << 7) | (pll_src << 6) | st->buf[1] = (en_pll << 7) | (pll_src << 6) |
...@@ -352,6 +385,7 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, ...@@ -352,6 +385,7 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
st->buf[9] = dsuScaler & 0xff; /* LSB */ st->buf[9] = dsuScaler & 0xff; /* LSB */
ret = dib0700_ctrl_wr(d, st->buf, 10); ret = dib0700_ctrl_wr(d, st->buf, 10);
mutex_unlock(&d->usb_mutex);
return ret; return ret;
} }
...@@ -360,10 +394,16 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) ...@@ -360,10 +394,16 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz)
{ {
struct dib0700_state *st = d->priv; struct dib0700_state *st = d->priv;
u16 divider; u16 divider;
int ret;
if (scl_kHz == 0) if (scl_kHz == 0)
return -EINVAL; return -EINVAL;
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
deb_info("could not acquire lock");
return 0;
}
st->buf[0] = REQUEST_SET_I2C_PARAM; st->buf[0] = REQUEST_SET_I2C_PARAM;
divider = (u16) (30000 / scl_kHz); divider = (u16) (30000 / scl_kHz);
st->buf[1] = 0; st->buf[1] = 0;
...@@ -379,7 +419,11 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) ...@@ -379,7 +419,11 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz)
deb_info("setting I2C speed: %04x %04x %04x (%d kHz).", deb_info("setting I2C speed: %04x %04x %04x (%d kHz).",
(st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) | (st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) |
st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz); st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz);
return dib0700_ctrl_wr(d, st->buf, 8);
ret = dib0700_ctrl_wr(d, st->buf, 8);
mutex_unlock(&d->usb_mutex);
return ret;
} }
...@@ -515,6 +559,11 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) ...@@ -515,6 +559,11 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
} }
} }
if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) {
deb_info("could not acquire lock");
return 0;
}
st->buf[0] = REQUEST_ENABLE_VIDEO; st->buf[0] = REQUEST_ENABLE_VIDEO;
/* this bit gives a kind of command, /* this bit gives a kind of command,
* rather than enabling something or not */ * rather than enabling something or not */
...@@ -548,7 +597,10 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) ...@@ -548,7 +597,10 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]); deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]);
return dib0700_ctrl_wr(adap->dev, st->buf, 4); ret = dib0700_ctrl_wr(adap->dev, st->buf, 4);
mutex_unlock(&adap->dev->usb_mutex);
return ret;
} }
int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
...@@ -557,6 +609,11 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) ...@@ -557,6 +609,11 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
struct dib0700_state *st = d->priv; struct dib0700_state *st = d->priv;
int new_proto, ret; int new_proto, ret;
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
deb_info("could not acquire lock");
return 0;
}
st->buf[0] = REQUEST_SET_RC; st->buf[0] = REQUEST_SET_RC;
st->buf[1] = 0; st->buf[1] = 0;
st->buf[2] = 0; st->buf[2] = 0;
...@@ -567,23 +624,29 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) ...@@ -567,23 +624,29 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
else if (rc_type == RC_TYPE_NEC) else if (rc_type == RC_TYPE_NEC)
new_proto = 0; new_proto = 0;
else if (rc_type == RC_TYPE_RC6) { else if (rc_type == RC_TYPE_RC6) {
if (st->fw_version < 0x10200) if (st->fw_version < 0x10200) {
return -EINVAL; ret = -EINVAL;
goto out;
}
new_proto = 2; new_proto = 2;
} else } else {
return -EINVAL; ret = -EINVAL;
goto out;
}
st->buf[1] = new_proto; st->buf[1] = new_proto;
ret = dib0700_ctrl_wr(d, st->buf, 3); ret = dib0700_ctrl_wr(d, st->buf, 3);
if (ret < 0) { if (ret < 0) {
err("ir protocol setup failed"); err("ir protocol setup failed");
return ret; goto out;
} }
d->props.rc.core.protocol = rc_type; d->props.rc.core.protocol = rc_type;
out:
mutex_unlock(&d->usb_mutex);
return ret; return ret;
} }
......
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