|
Takashi Iwai |
9e9ebe |
From 1499ecaea9d2ba68d5e18d80573b4561a8dc4ee7 Mon Sep 17 00:00:00 2001
|
|
Takashi Iwai |
9e9ebe |
From: Anssi Hannula <anssi.hannula@bitwise.fi>
|
|
Takashi Iwai |
9e9ebe |
Date: Mon, 10 Oct 2022 17:08:26 +0200
|
|
Takashi Iwai |
9e9ebe |
Subject: [PATCH] can: kvaser_usb_leaf: Fix overread with an invalid command
|
|
Takashi Iwai |
9e9ebe |
Git-commit: 1499ecaea9d2ba68d5e18d80573b4561a8dc4ee7
|
|
Takashi Iwai |
9e9ebe |
Patch-mainline: v6.1-rc1
|
|
Takashi Iwai |
9e9ebe |
References: git-fixes
|
|
Takashi Iwai |
9e9ebe |
|
|
Takashi Iwai |
9e9ebe |
For command events read from the device,
|
|
Takashi Iwai |
9e9ebe |
kvaser_usb_leaf_read_bulk_callback() verifies that cmd->len does not
|
|
Takashi Iwai |
9e9ebe |
exceed the size of the received data, but the actual kvaser_cmd handlers
|
|
Takashi Iwai |
9e9ebe |
will happily read any kvaser_cmd fields without checking for cmd->len.
|
|
Takashi Iwai |
9e9ebe |
|
|
Takashi Iwai |
9e9ebe |
This can cause an overread if the last cmd in the buffer is shorter than
|
|
Takashi Iwai |
9e9ebe |
expected for the command type (with cmd->len showing the actual short
|
|
Takashi Iwai |
9e9ebe |
size).
|
|
Takashi Iwai |
9e9ebe |
|
|
Takashi Iwai |
9e9ebe |
Maximum overread seems to be 22 bytes (CMD_LEAF_LOG_MESSAGE), some of
|
|
Takashi Iwai |
9e9ebe |
which are delivered to userspace as-is.
|
|
Takashi Iwai |
9e9ebe |
|
|
Takashi Iwai |
9e9ebe |
Fix that by verifying the length of command before handling it.
|
|
Takashi Iwai |
9e9ebe |
|
|
Takashi Iwai |
9e9ebe |
This issue can only occur after RX URBs have been set up, i.e. the
|
|
Takashi Iwai |
9e9ebe |
interface has been opened at least once.
|
|
Takashi Iwai |
9e9ebe |
|
|
Takashi Iwai |
9e9ebe |
Cc: stable@vger.kernel.org
|
|
Takashi Iwai |
9e9ebe |
Fixes: 080f40a6fa28 ("can: kvaser_usb: Add support for Kvaser CAN/USB devices")
|
|
Takashi Iwai |
9e9ebe |
Tested-by: Jimmy Assarsson <extja@kvaser.com>
|
|
Takashi Iwai |
9e9ebe |
Signed-off-by: Anssi Hannula <anssi.hannula@bitwise.fi>
|
|
Takashi Iwai |
9e9ebe |
Signed-off-by: Jimmy Assarsson <extja@kvaser.com>
|
|
Takashi Iwai |
9e9ebe |
Link: https://lore.kernel.org/all/20221010150829.199676-2-extja@kvaser.com
|
|
Takashi Iwai |
9e9ebe |
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
|
|
Takashi Iwai |
9e9ebe |
Acked-by: Takashi Iwai <tiwai@suse.de>
|
|
Takashi Iwai |
9e9ebe |
|
|
Takashi Iwai |
9e9ebe |
---
|
|
Takashi Iwai |
9e9ebe |
drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 75 +++++++++++++++++++++++
|
|
Takashi Iwai |
9e9ebe |
1 file changed, 75 insertions(+)
|
|
Takashi Iwai |
9e9ebe |
|
|
Takashi Iwai |
9e9ebe |
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
|
|
Takashi Iwai |
9e9ebe |
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
|
|
Takashi Iwai |
9e9ebe |
@@ -310,6 +310,38 @@ struct kvaser_cmd {
|
|
Takashi Iwai |
9e9ebe |
} u;
|
|
Takashi Iwai |
9e9ebe |
} __packed;
|
|
Takashi Iwai |
9e9ebe |
|
|
Takashi Iwai |
9e9ebe |
+#define CMD_SIZE_ANY 0xff
|
|
Takashi Iwai |
9e9ebe |
+#define kvaser_fsize(field) sizeof_field(struct kvaser_cmd, field)
|
|
Takashi Iwai |
9e9ebe |
+
|
|
Takashi Iwai |
9e9ebe |
+static const u8 kvaser_usb_leaf_cmd_sizes_leaf[] = {
|
|
Takashi Iwai |
9e9ebe |
+ [CMD_START_CHIP_REPLY] = kvaser_fsize(u.simple),
|
|
Takashi Iwai |
9e9ebe |
+ [CMD_STOP_CHIP_REPLY] = kvaser_fsize(u.simple),
|
|
Takashi Iwai |
9e9ebe |
+ [CMD_GET_CARD_INFO_REPLY] = kvaser_fsize(u.cardinfo),
|
|
Takashi Iwai |
9e9ebe |
+ [CMD_TX_ACKNOWLEDGE] = kvaser_fsize(u.tx_acknowledge_header),
|
|
Takashi Iwai |
9e9ebe |
+ [CMD_GET_SOFTWARE_INFO_REPLY] = kvaser_fsize(u.leaf.softinfo),
|
|
Takashi Iwai |
9e9ebe |
+ [CMD_RX_STD_MESSAGE] = kvaser_fsize(u.leaf.rx_can),
|
|
Takashi Iwai |
9e9ebe |
+ [CMD_RX_EXT_MESSAGE] = kvaser_fsize(u.leaf.rx_can),
|
|
Takashi Iwai |
9e9ebe |
+ [CMD_LEAF_LOG_MESSAGE] = kvaser_fsize(u.leaf.log_message),
|
|
Takashi Iwai |
9e9ebe |
+ [CMD_CHIP_STATE_EVENT] = kvaser_fsize(u.leaf.chip_state_event),
|
|
Takashi Iwai |
9e9ebe |
+ [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.leaf.error_event),
|
|
Takashi Iwai |
9e9ebe |
+ /* ignored events: */
|
|
Takashi Iwai |
9e9ebe |
+ [CMD_FLUSH_QUEUE_REPLY] = CMD_SIZE_ANY,
|
|
Takashi Iwai |
9e9ebe |
+};
|
|
Takashi Iwai |
9e9ebe |
+
|
|
Takashi Iwai |
9e9ebe |
+static const u8 kvaser_usb_leaf_cmd_sizes_usbcan[] = {
|
|
Takashi Iwai |
9e9ebe |
+ [CMD_START_CHIP_REPLY] = kvaser_fsize(u.simple),
|
|
Takashi Iwai |
9e9ebe |
+ [CMD_STOP_CHIP_REPLY] = kvaser_fsize(u.simple),
|
|
Takashi Iwai |
9e9ebe |
+ [CMD_GET_CARD_INFO_REPLY] = kvaser_fsize(u.cardinfo),
|
|
Takashi Iwai |
9e9ebe |
+ [CMD_TX_ACKNOWLEDGE] = kvaser_fsize(u.tx_acknowledge_header),
|
|
Takashi Iwai |
9e9ebe |
+ [CMD_GET_SOFTWARE_INFO_REPLY] = kvaser_fsize(u.usbcan.softinfo),
|
|
Takashi Iwai |
9e9ebe |
+ [CMD_RX_STD_MESSAGE] = kvaser_fsize(u.usbcan.rx_can),
|
|
Takashi Iwai |
9e9ebe |
+ [CMD_RX_EXT_MESSAGE] = kvaser_fsize(u.usbcan.rx_can),
|
|
Takashi Iwai |
9e9ebe |
+ [CMD_CHIP_STATE_EVENT] = kvaser_fsize(u.usbcan.chip_state_event),
|
|
Takashi Iwai |
9e9ebe |
+ [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.usbcan.error_event),
|
|
Takashi Iwai |
9e9ebe |
+ /* ignored events: */
|
|
Takashi Iwai |
9e9ebe |
+ [CMD_USBCAN_CLOCK_OVERFLOW_EVENT] = CMD_SIZE_ANY,
|
|
Takashi Iwai |
9e9ebe |
+};
|
|
Takashi Iwai |
9e9ebe |
+
|
|
Takashi Iwai |
9e9ebe |
/* Summary of a kvaser error event, for a unified Leaf/Usbcan error
|
|
Takashi Iwai |
9e9ebe |
* handling. Some discrepancies between the two families exist:
|
|
Takashi Iwai |
9e9ebe |
*
|
|
Takashi Iwai |
9e9ebe |
@@ -397,6 +429,43 @@ static const struct kvaser_usb_dev_cfg k
|
|
Takashi Iwai |
9e9ebe |
.bittiming_const = &kvaser_usb_flexc_bittiming_const,
|
|
Takashi Iwai |
9e9ebe |
};
|
|
Takashi Iwai |
9e9ebe |
|
|
Takashi Iwai |
9e9ebe |
+static int kvaser_usb_leaf_verify_size(const struct kvaser_usb *dev,
|
|
Takashi Iwai |
9e9ebe |
+ const struct kvaser_cmd *cmd)
|
|
Takashi Iwai |
9e9ebe |
+{
|
|
Takashi Iwai |
9e9ebe |
+ /* buffer size >= cmd->len ensured by caller */
|
|
Takashi Iwai |
9e9ebe |
+ u8 min_size = 0;
|
|
Takashi Iwai |
9e9ebe |
+
|
|
Takashi Iwai |
9e9ebe |
+ switch (dev->driver_info->family) {
|
|
Takashi Iwai |
9e9ebe |
+ case KVASER_LEAF:
|
|
Takashi Iwai |
9e9ebe |
+ if (cmd->id < ARRAY_SIZE(kvaser_usb_leaf_cmd_sizes_leaf))
|
|
Takashi Iwai |
9e9ebe |
+ min_size = kvaser_usb_leaf_cmd_sizes_leaf[cmd->id];
|
|
Takashi Iwai |
9e9ebe |
+ break;
|
|
Takashi Iwai |
9e9ebe |
+ case KVASER_USBCAN:
|
|
Takashi Iwai |
9e9ebe |
+ if (cmd->id < ARRAY_SIZE(kvaser_usb_leaf_cmd_sizes_usbcan))
|
|
Takashi Iwai |
9e9ebe |
+ min_size = kvaser_usb_leaf_cmd_sizes_usbcan[cmd->id];
|
|
Takashi Iwai |
9e9ebe |
+ break;
|
|
Takashi Iwai |
9e9ebe |
+ }
|
|
Takashi Iwai |
9e9ebe |
+
|
|
Takashi Iwai |
9e9ebe |
+ if (min_size == CMD_SIZE_ANY)
|
|
Takashi Iwai |
9e9ebe |
+ return 0;
|
|
Takashi Iwai |
9e9ebe |
+
|
|
Takashi Iwai |
9e9ebe |
+ if (min_size) {
|
|
Takashi Iwai |
9e9ebe |
+ min_size += CMD_HEADER_LEN;
|
|
Takashi Iwai |
9e9ebe |
+ if (cmd->len >= min_size)
|
|
Takashi Iwai |
9e9ebe |
+ return 0;
|
|
Takashi Iwai |
9e9ebe |
+
|
|
Takashi Iwai |
9e9ebe |
+ dev_err_ratelimited(&dev->intf->dev,
|
|
Takashi Iwai |
9e9ebe |
+ "Received command %u too short (size %u, needed %u)",
|
|
Takashi Iwai |
9e9ebe |
+ cmd->id, cmd->len, min_size);
|
|
Takashi Iwai |
9e9ebe |
+ return -EIO;
|
|
Takashi Iwai |
9e9ebe |
+ }
|
|
Takashi Iwai |
9e9ebe |
+
|
|
Takashi Iwai |
9e9ebe |
+ dev_warn_ratelimited(&dev->intf->dev,
|
|
Takashi Iwai |
9e9ebe |
+ "Unhandled command (%d, size %d)\n",
|
|
Takashi Iwai |
9e9ebe |
+ cmd->id, cmd->len);
|
|
Takashi Iwai |
9e9ebe |
+ return -EINVAL;
|
|
Takashi Iwai |
9e9ebe |
+}
|
|
Takashi Iwai |
9e9ebe |
+
|
|
Takashi Iwai |
9e9ebe |
static void *
|
|
Takashi Iwai |
9e9ebe |
kvaser_usb_leaf_frame_to_cmd(const struct kvaser_usb_net_priv *priv,
|
|
Takashi Iwai |
9e9ebe |
const struct sk_buff *skb, int *frame_len,
|
|
Takashi Iwai |
9e9ebe |
@@ -504,6 +573,9 @@ static int kvaser_usb_leaf_wait_cmd(cons
|
|
Takashi Iwai |
9e9ebe |
end:
|
|
Takashi Iwai |
9e9ebe |
kfree(buf);
|
|
Takashi Iwai |
9e9ebe |
|
|
Takashi Iwai |
9e9ebe |
+ if (err == 0)
|
|
Takashi Iwai |
9e9ebe |
+ err = kvaser_usb_leaf_verify_size(dev, cmd);
|
|
Takashi Iwai |
9e9ebe |
+
|
|
Takashi Iwai |
9e9ebe |
return err;
|
|
Takashi Iwai |
9e9ebe |
}
|
|
Takashi Iwai |
9e9ebe |
|
|
Takashi Iwai |
9e9ebe |
@@ -1135,6 +1207,9 @@ static void kvaser_usb_leaf_stop_chip_re
|
|
Takashi Iwai |
9e9ebe |
static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev,
|
|
Takashi Iwai |
9e9ebe |
const struct kvaser_cmd *cmd)
|
|
Takashi Iwai |
9e9ebe |
{
|
|
Takashi Iwai |
9e9ebe |
+ if (kvaser_usb_leaf_verify_size(dev, cmd) < 0)
|
|
Takashi Iwai |
9e9ebe |
+ return;
|
|
Takashi Iwai |
9e9ebe |
+
|
|
Takashi Iwai |
9e9ebe |
switch (cmd->id) {
|
|
Takashi Iwai |
9e9ebe |
case CMD_START_CHIP_REPLY:
|
|
Takashi Iwai |
9e9ebe |
kvaser_usb_leaf_start_chip_reply(dev, cmd);
|