Commit ff05cf09 authored by Sean Young's avatar Sean Young Committed by Mauro Carvalho Chehab

media: mceusb: do not read data parameters unless required

This causes out-of-bounds read on device probe.

BUG: KASAN: slab-out-of-bounds in mceusb_dev_printdata+0xdc/0x830 [mceusb]
Signed-off-by: default avatarSean Young <sean@mess.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent 89d8a2cc
...@@ -538,12 +538,12 @@ static int mceusb_cmd_datasize(u8 cmd, u8 subcmd) ...@@ -538,12 +538,12 @@ static int mceusb_cmd_datasize(u8 cmd, u8 subcmd)
return datasize; return datasize;
} }
static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, static void mceusb_dev_printdata(struct mceusb_dev *ir, u8 *buf, int buf_len,
int buf_len, int offset, int len, bool out) int offset, int len, bool out)
{ {
#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) #if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
char *inout; char *inout;
u8 cmd, subcmd, data1, data2, data3, data4; u8 cmd, subcmd, *data;
struct device *dev = ir->dev; struct device *dev = ir->dev;
int start, skip = 0; int start, skip = 0;
u32 carrier, period; u32 carrier, period;
...@@ -564,17 +564,14 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, ...@@ -564,17 +564,14 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
start = offset + skip; start = offset + skip;
cmd = buf[start] & 0xff; cmd = buf[start] & 0xff;
subcmd = buf[start + 1] & 0xff; subcmd = buf[start + 1] & 0xff;
data1 = buf[start + 2] & 0xff; data = buf + start + 2;
data2 = buf[start + 3] & 0xff;
data3 = buf[start + 4] & 0xff;
data4 = buf[start + 5] & 0xff;
switch (cmd) { switch (cmd) {
case MCE_CMD_NULL: case MCE_CMD_NULL:
if (subcmd == MCE_CMD_NULL) if (subcmd == MCE_CMD_NULL)
break; break;
if ((subcmd == MCE_CMD_PORT_SYS) && if ((subcmd == MCE_CMD_PORT_SYS) &&
(data1 == MCE_CMD_RESUME)) (data[0] == MCE_CMD_RESUME))
dev_dbg(dev, "Device resume requested"); dev_dbg(dev, "Device resume requested");
else else
dev_dbg(dev, "Unknown command 0x%02x 0x%02x", dev_dbg(dev, "Unknown command 0x%02x 0x%02x",
...@@ -585,7 +582,7 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, ...@@ -585,7 +582,7 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
case MCE_RSP_EQEMVER: case MCE_RSP_EQEMVER:
if (!out) if (!out)
dev_dbg(dev, "Emulator interface version %x", dev_dbg(dev, "Emulator interface version %x",
data1); data[0]);
break; break;
case MCE_CMD_G_REVISION: case MCE_CMD_G_REVISION:
if (len == 2) if (len == 2)
...@@ -603,13 +600,13 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, ...@@ -603,13 +600,13 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
case MCE_RSP_EQWAKEVERSION: case MCE_RSP_EQWAKEVERSION:
if (!out) if (!out)
dev_dbg(dev, "Wake version, proto: 0x%02x, payload: 0x%02x, address: 0x%02x, version: 0x%02x", dev_dbg(dev, "Wake version, proto: 0x%02x, payload: 0x%02x, address: 0x%02x, version: 0x%02x",
data1, data2, data3, data4); data[0], data[1], data[2], data[3]);
break; break;
case MCE_RSP_GETPORTSTATUS: case MCE_RSP_GETPORTSTATUS:
if (!out) if (!out)
/* We use data1 + 1 here, to match hw labels */ /* We use data1 + 1 here, to match hw labels */
dev_dbg(dev, "TX port %d: blaster is%s connected", dev_dbg(dev, "TX port %d: blaster is%s connected",
data1 + 1, data4 ? " not" : ""); data[0] + 1, data[3] ? " not" : "");
break; break;
case MCE_CMD_FLASHLED: case MCE_CMD_FLASHLED:
dev_dbg(dev, "Attempting to flash LED"); dev_dbg(dev, "Attempting to flash LED");
...@@ -630,11 +627,11 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, ...@@ -630,11 +627,11 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
break; break;
case MCE_CMD_UNKNOWN: case MCE_CMD_UNKNOWN:
dev_dbg(dev, "Resp to 9f 05 of 0x%02x 0x%02x", dev_dbg(dev, "Resp to 9f 05 of 0x%02x 0x%02x",
data1, data2); data[0], data[1]);
break; break;
case MCE_RSP_EQIRCFS: case MCE_RSP_EQIRCFS:
period = DIV_ROUND_CLOSEST( period = DIV_ROUND_CLOSEST((1U << data[0] * 2) *
(1U << data1 * 2) * (data2 + 1), 10); (data[1] + 1), 10);
if (!period) if (!period)
break; break;
carrier = (1000 * 1000) / period; carrier = (1000 * 1000) / period;
...@@ -646,11 +643,12 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, ...@@ -646,11 +643,12 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
break; break;
case MCE_RSP_EQIRTXPORTS: case MCE_RSP_EQIRTXPORTS:
dev_dbg(dev, "%s transmit blaster mask of 0x%02x", dev_dbg(dev, "%s transmit blaster mask of 0x%02x",
inout, data1); inout, data[0]);
break; break;
case MCE_RSP_EQIRTIMEOUT: case MCE_RSP_EQIRTIMEOUT:
/* value is in units of 50us, so x*50/1000 ms */ /* value is in units of 50us, so x*50/1000 ms */
period = ((data1 << 8) | data2) * MCE_TIME_UNIT / 1000; period = ((data[0] << 8) | data[1]) *
MCE_TIME_UNIT / 1000;
dev_dbg(dev, "%s receive timeout of %d ms", dev_dbg(dev, "%s receive timeout of %d ms",
inout, period); inout, period);
break; break;
...@@ -662,7 +660,7 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, ...@@ -662,7 +660,7 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
break; break;
case MCE_RSP_EQIRRXPORTEN: case MCE_RSP_EQIRRXPORTEN:
dev_dbg(dev, "%s %s-range receive sensor in use", dev_dbg(dev, "%s %s-range receive sensor in use",
inout, data1 == 0x02 ? "short" : "long"); inout, data[0] == 0x02 ? "short" : "long");
break; break;
case MCE_CMD_GETIRRXPORTEN: case MCE_CMD_GETIRRXPORTEN:
/* aka MCE_RSP_EQIRRXCFCNT */ /* aka MCE_RSP_EQIRRXCFCNT */
...@@ -670,13 +668,13 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, ...@@ -670,13 +668,13 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
dev_dbg(dev, "Get receive sensor"); dev_dbg(dev, "Get receive sensor");
else if (ir->learning_enabled) else if (ir->learning_enabled)
dev_dbg(dev, "RX pulse count: %d", dev_dbg(dev, "RX pulse count: %d",
((data1 << 8) | data2)); ((data[0] << 8) | data[1]));
break; break;
case MCE_RSP_EQIRNUMPORTS: case MCE_RSP_EQIRNUMPORTS:
if (out) if (out)
break; break;
dev_dbg(dev, "Num TX ports: %x, num RX ports: %x", dev_dbg(dev, "Num TX ports: %x, num RX ports: %x",
data1, data2); data[0], data[1]);
break; break;
case MCE_RSP_CMD_ILLEGAL: case MCE_RSP_CMD_ILLEGAL:
dev_dbg(dev, "Illegal PORT_IR command"); dev_dbg(dev, "Illegal PORT_IR command");
......
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