Commit 0cf3cae9 authored by Paolo Abeni's avatar Paolo Abeni

Merge tag 'linux-can-fixes-for-6.1-20221011' of...

Merge tag 'linux-can-fixes-for-6.1-20221011' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can

Marc Kleine-Budde says:

====================
pull-request: can 2022-10-11

this is a pull request of 4 patches for net/main.

Anssi Hannula and Jimmy Assarsson contribute 4 patches for the
kvaser_usb driver. A check for actual received length of USB transfers
is added, the use of an uninitialized completion is fixed, the TX
queue is re-synced after restart, and the CAN state is fixed after
restart.

* tag 'linux-can-fixes-for-6.1-20221011' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can:
  can: kvaser_usb_leaf: Fix CAN state after restart
  can: kvaser_usb_leaf: Fix TX queue out of sync after restart
  can: kvaser_usb: Fix use of uninitialized completion
  can: kvaser_usb_leaf: Fix overread with an invalid command
====================

Link: https://lore.kernel.org/r/20221011074815.397301-1-mkl@pengutronix.deSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents b15e2e49 8183602b
...@@ -178,6 +178,8 @@ struct kvaser_usb_dev_cfg { ...@@ -178,6 +178,8 @@ struct kvaser_usb_dev_cfg {
extern const struct kvaser_usb_dev_ops kvaser_usb_hydra_dev_ops; extern const struct kvaser_usb_dev_ops kvaser_usb_hydra_dev_ops;
extern const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops; extern const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops;
void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv);
int kvaser_usb_recv_cmd(const struct kvaser_usb *dev, void *cmd, int len, int kvaser_usb_recv_cmd(const struct kvaser_usb *dev, void *cmd, int len,
int *actual_len); int *actual_len);
......
...@@ -477,7 +477,7 @@ static void kvaser_usb_reset_tx_urb_contexts(struct kvaser_usb_net_priv *priv) ...@@ -477,7 +477,7 @@ static void kvaser_usb_reset_tx_urb_contexts(struct kvaser_usb_net_priv *priv)
/* This method might sleep. Do not call it in the atomic context /* This method might sleep. Do not call it in the atomic context
* of URB completions. * of URB completions.
*/ */
static void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv) void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv)
{ {
usb_kill_anchored_urbs(&priv->tx_submitted); usb_kill_anchored_urbs(&priv->tx_submitted);
kvaser_usb_reset_tx_urb_contexts(priv); kvaser_usb_reset_tx_urb_contexts(priv);
...@@ -729,6 +729,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel) ...@@ -729,6 +729,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)
init_usb_anchor(&priv->tx_submitted); init_usb_anchor(&priv->tx_submitted);
init_completion(&priv->start_comp); init_completion(&priv->start_comp);
init_completion(&priv->stop_comp); init_completion(&priv->stop_comp);
init_completion(&priv->flush_comp);
priv->can.ctrlmode_supported = 0; priv->can.ctrlmode_supported = 0;
priv->dev = dev; priv->dev = dev;
......
...@@ -1916,7 +1916,7 @@ static int kvaser_usb_hydra_flush_queue(struct kvaser_usb_net_priv *priv) ...@@ -1916,7 +1916,7 @@ static int kvaser_usb_hydra_flush_queue(struct kvaser_usb_net_priv *priv)
{ {
int err; int err;
init_completion(&priv->flush_comp); reinit_completion(&priv->flush_comp);
err = kvaser_usb_hydra_send_simple_cmd(priv->dev, CMD_FLUSH_QUEUE, err = kvaser_usb_hydra_send_simple_cmd(priv->dev, CMD_FLUSH_QUEUE,
priv->channel); priv->channel);
......
...@@ -310,6 +310,38 @@ struct kvaser_cmd { ...@@ -310,6 +310,38 @@ struct kvaser_cmd {
} u; } u;
} __packed; } __packed;
#define CMD_SIZE_ANY 0xff
#define kvaser_fsize(field) sizeof_field(struct kvaser_cmd, field)
static const u8 kvaser_usb_leaf_cmd_sizes_leaf[] = {
[CMD_START_CHIP_REPLY] = kvaser_fsize(u.simple),
[CMD_STOP_CHIP_REPLY] = kvaser_fsize(u.simple),
[CMD_GET_CARD_INFO_REPLY] = kvaser_fsize(u.cardinfo),
[CMD_TX_ACKNOWLEDGE] = kvaser_fsize(u.tx_acknowledge_header),
[CMD_GET_SOFTWARE_INFO_REPLY] = kvaser_fsize(u.leaf.softinfo),
[CMD_RX_STD_MESSAGE] = kvaser_fsize(u.leaf.rx_can),
[CMD_RX_EXT_MESSAGE] = kvaser_fsize(u.leaf.rx_can),
[CMD_LEAF_LOG_MESSAGE] = kvaser_fsize(u.leaf.log_message),
[CMD_CHIP_STATE_EVENT] = kvaser_fsize(u.leaf.chip_state_event),
[CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.leaf.error_event),
/* ignored events: */
[CMD_FLUSH_QUEUE_REPLY] = CMD_SIZE_ANY,
};
static const u8 kvaser_usb_leaf_cmd_sizes_usbcan[] = {
[CMD_START_CHIP_REPLY] = kvaser_fsize(u.simple),
[CMD_STOP_CHIP_REPLY] = kvaser_fsize(u.simple),
[CMD_GET_CARD_INFO_REPLY] = kvaser_fsize(u.cardinfo),
[CMD_TX_ACKNOWLEDGE] = kvaser_fsize(u.tx_acknowledge_header),
[CMD_GET_SOFTWARE_INFO_REPLY] = kvaser_fsize(u.usbcan.softinfo),
[CMD_RX_STD_MESSAGE] = kvaser_fsize(u.usbcan.rx_can),
[CMD_RX_EXT_MESSAGE] = kvaser_fsize(u.usbcan.rx_can),
[CMD_CHIP_STATE_EVENT] = kvaser_fsize(u.usbcan.chip_state_event),
[CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.usbcan.error_event),
/* ignored events: */
[CMD_USBCAN_CLOCK_OVERFLOW_EVENT] = CMD_SIZE_ANY,
};
/* Summary of a kvaser error event, for a unified Leaf/Usbcan error /* Summary of a kvaser error event, for a unified Leaf/Usbcan error
* handling. Some discrepancies between the two families exist: * handling. Some discrepancies between the two families exist:
* *
...@@ -397,6 +429,43 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_32mhz = { ...@@ -397,6 +429,43 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_32mhz = {
.bittiming_const = &kvaser_usb_flexc_bittiming_const, .bittiming_const = &kvaser_usb_flexc_bittiming_const,
}; };
static int kvaser_usb_leaf_verify_size(const struct kvaser_usb *dev,
const struct kvaser_cmd *cmd)
{
/* buffer size >= cmd->len ensured by caller */
u8 min_size = 0;
switch (dev->driver_info->family) {
case KVASER_LEAF:
if (cmd->id < ARRAY_SIZE(kvaser_usb_leaf_cmd_sizes_leaf))
min_size = kvaser_usb_leaf_cmd_sizes_leaf[cmd->id];
break;
case KVASER_USBCAN:
if (cmd->id < ARRAY_SIZE(kvaser_usb_leaf_cmd_sizes_usbcan))
min_size = kvaser_usb_leaf_cmd_sizes_usbcan[cmd->id];
break;
}
if (min_size == CMD_SIZE_ANY)
return 0;
if (min_size) {
min_size += CMD_HEADER_LEN;
if (cmd->len >= min_size)
return 0;
dev_err_ratelimited(&dev->intf->dev,
"Received command %u too short (size %u, needed %u)",
cmd->id, cmd->len, min_size);
return -EIO;
}
dev_warn_ratelimited(&dev->intf->dev,
"Unhandled command (%d, size %d)\n",
cmd->id, cmd->len);
return -EINVAL;
}
static void * static void *
kvaser_usb_leaf_frame_to_cmd(const struct kvaser_usb_net_priv *priv, kvaser_usb_leaf_frame_to_cmd(const struct kvaser_usb_net_priv *priv,
const struct sk_buff *skb, int *cmd_len, const struct sk_buff *skb, int *cmd_len,
...@@ -502,6 +571,9 @@ static int kvaser_usb_leaf_wait_cmd(const struct kvaser_usb *dev, u8 id, ...@@ -502,6 +571,9 @@ static int kvaser_usb_leaf_wait_cmd(const struct kvaser_usb *dev, u8 id,
end: end:
kfree(buf); kfree(buf);
if (err == 0)
err = kvaser_usb_leaf_verify_size(dev, cmd);
return err; return err;
} }
...@@ -1133,6 +1205,9 @@ static void kvaser_usb_leaf_stop_chip_reply(const struct kvaser_usb *dev, ...@@ -1133,6 +1205,9 @@ static void kvaser_usb_leaf_stop_chip_reply(const struct kvaser_usb *dev,
static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev, static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev,
const struct kvaser_cmd *cmd) const struct kvaser_cmd *cmd)
{ {
if (kvaser_usb_leaf_verify_size(dev, cmd) < 0)
return;
switch (cmd->id) { switch (cmd->id) {
case CMD_START_CHIP_REPLY: case CMD_START_CHIP_REPLY:
kvaser_usb_leaf_start_chip_reply(dev, cmd); kvaser_usb_leaf_start_chip_reply(dev, cmd);
...@@ -1351,9 +1426,13 @@ static int kvaser_usb_leaf_set_mode(struct net_device *netdev, ...@@ -1351,9 +1426,13 @@ static int kvaser_usb_leaf_set_mode(struct net_device *netdev,
switch (mode) { switch (mode) {
case CAN_MODE_START: case CAN_MODE_START:
kvaser_usb_unlink_tx_urbs(priv);
err = kvaser_usb_leaf_simple_cmd_async(priv, CMD_START_CHIP); err = kvaser_usb_leaf_simple_cmd_async(priv, CMD_START_CHIP);
if (err) if (err)
return err; return err;
priv->can.state = CAN_STATE_ERROR_ACTIVE;
break; break;
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
......
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