Commit b1a9599a authored by Michael Büsch's avatar Michael Büsch Committed by Mauro Carvalho Chehab

[media] af9035: Add USB read checksumming

This adds USB message read checksumming to protect against
device and bus errors.
It also adds a read length check to avoid returning garbage from
the buffer, if the device truncated the message.
Signed-off-by: default avatarMichael Buesch <m@bues.ch>
Signed-off-by: default avatarAntti Palosaari <crope@iki.fi>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 812fe6d9
...@@ -36,6 +36,22 @@ static struct af9033_config af9035_af9033_config[] = { ...@@ -36,6 +36,22 @@ static struct af9033_config af9035_af9033_config[] = {
} }
}; };
static u16 af9035_checksum(const u8 *buf, size_t len)
{
size_t i;
u16 checksum = 0;
for (i = 1; i < len; i++) {
if (i % 2)
checksum += buf[i] << 8;
else
checksum += buf[i];
}
checksum = ~checksum;
return checksum;
}
static int af9035_ctrl_msg(struct usb_device *udev, struct usb_req *req) static int af9035_ctrl_msg(struct usb_device *udev, struct usb_req *req)
{ {
#define BUF_LEN 63 #define BUF_LEN 63
...@@ -44,11 +60,11 @@ static int af9035_ctrl_msg(struct usb_device *udev, struct usb_req *req) ...@@ -44,11 +60,11 @@ static int af9035_ctrl_msg(struct usb_device *udev, struct usb_req *req)
#define CHECKSUM_LEN 2 #define CHECKSUM_LEN 2
#define USB_TIMEOUT 2000 #define USB_TIMEOUT 2000
int ret, i, act_len; int ret, act_len;
u8 buf[BUF_LEN]; u8 buf[BUF_LEN];
u32 msg_len; u32 msg_len;
static u8 seq; /* packet sequence number */ static u8 seq; /* packet sequence number */
u16 checksum = 0; u16 checksum, tmpsum;
/* buffer overflow check */ /* buffer overflow check */
if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) || if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) ||
...@@ -69,14 +85,7 @@ static int af9035_ctrl_msg(struct usb_device *udev, struct usb_req *req) ...@@ -69,14 +85,7 @@ static int af9035_ctrl_msg(struct usb_device *udev, struct usb_req *req)
memcpy(&buf[4], req->wbuf, req->wlen); memcpy(&buf[4], req->wbuf, req->wlen);
/* calc and add checksum */ /* calc and add checksum */
for (i = 1; i < buf[0]-1; i++) { checksum = af9035_checksum(buf, buf[0] - 1);
if (i % 2)
checksum += buf[i] << 8;
else
checksum += buf[i];
}
checksum = ~checksum;
buf[buf[0]-1] = (checksum >> 8); buf[buf[0]-1] = (checksum >> 8);
buf[buf[0]-0] = (checksum & 0xff); buf[buf[0]-0] = (checksum & 0xff);
...@@ -106,7 +115,23 @@ static int af9035_ctrl_msg(struct usb_device *udev, struct usb_req *req) ...@@ -106,7 +115,23 @@ static int af9035_ctrl_msg(struct usb_device *udev, struct usb_req *req)
ret = -EIO; ret = -EIO;
goto err_mutex_unlock; goto err_mutex_unlock;
} }
if (act_len != msg_len) {
err("recv bulk message truncated (%d != %u)\n",
act_len, (unsigned int)msg_len);
ret = -EIO;
goto err_mutex_unlock;
}
/* verify checksum */
checksum = af9035_checksum(buf, act_len - 2);
tmpsum = (buf[act_len - 2] << 8) | buf[act_len - 1];
if (tmpsum != checksum) {
err("%s: command=%02X checksum mismatch (%04X != %04X)\n",
__func__, req->cmd,
(unsigned int)tmpsum, (unsigned int)checksum);
ret = -EIO;
goto err_mutex_unlock;
}
/* check status */ /* check status */
if (buf[2]) { if (buf[2]) {
pr_debug("%s: command=%02x failed fw error=%d\n", __func__, pr_debug("%s: command=%02x failed fw error=%d\n", __func__,
......
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