mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-09 14:14:00 +08:00
linux-can-fixes-for-6.1-20221011
-----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEBsvAIBsPu6mG7thcrX5LkNig010FAmNFHKQTHG1rbEBwZW5n dXRyb25peC5kZQAKCRCtfkuQ2KDTXV5qB/4uBePx05MWdxiXspIQ8XCFxGLIrSX7 59xvXMwfou4VcPxoRwT+5GGM1u+2UOIuiyoAwwxdv2WiWmDqsro0pY3U9pmPIeYX c8z+vx6u2k5vrR48J0zdo1zPm5PJo7jFgnrVZ207Ccz4cozSDEqM4yYp5AGwuwhq 0NIlcjeokGFdbshPZAuCYHkAJAEBbGtAAd/N32jwD6W381lvAaYvlCRsG0JVBXim rqPqT7x+hDTjt42c25RZUlsJwEVABt90d8qqQK5JB6bFls1WeP20XEbdD1ZwybDU VhU+/kcXlH9ImxXRGmSY2rFrN/IErrJw121QO0h1bmMgoTAyMsKeoeN0 =r17l -----END PGP SIGNATURE----- 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.de Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
0cf3cae969
@ -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_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 *actual_len);
|
||||
|
||||
|
@ -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
|
||||
* 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);
|
||||
kvaser_usb_reset_tx_urb_contexts(priv);
|
||||
@ -729,6 +729,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)
|
||||
init_usb_anchor(&priv->tx_submitted);
|
||||
init_completion(&priv->start_comp);
|
||||
init_completion(&priv->stop_comp);
|
||||
init_completion(&priv->flush_comp);
|
||||
priv->can.ctrlmode_supported = 0;
|
||||
|
||||
priv->dev = dev;
|
||||
|
@ -1916,7 +1916,7 @@ static int kvaser_usb_hydra_flush_queue(struct kvaser_usb_net_priv *priv)
|
||||
{
|
||||
int err;
|
||||
|
||||
init_completion(&priv->flush_comp);
|
||||
reinit_completion(&priv->flush_comp);
|
||||
|
||||
err = kvaser_usb_hydra_send_simple_cmd(priv->dev, CMD_FLUSH_QUEUE,
|
||||
priv->channel);
|
||||
|
@ -310,6 +310,38 @@ struct kvaser_cmd {
|
||||
} u;
|
||||
} __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
|
||||
* 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 = {
|
||||
.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 *
|
||||
kvaser_usb_leaf_frame_to_cmd(const struct kvaser_usb_net_priv *priv,
|
||||
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,
|
||||
end:
|
||||
kfree(buf);
|
||||
|
||||
if (err == 0)
|
||||
err = kvaser_usb_leaf_verify_size(dev, cmd);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -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,
|
||||
const struct kvaser_cmd *cmd)
|
||||
{
|
||||
if (kvaser_usb_leaf_verify_size(dev, cmd) < 0)
|
||||
return;
|
||||
|
||||
switch (cmd->id) {
|
||||
case CMD_START_CHIP_REPLY:
|
||||
kvaser_usb_leaf_start_chip_reply(dev, cmd);
|
||||
@ -1351,9 +1426,13 @@ static int kvaser_usb_leaf_set_mode(struct net_device *netdev,
|
||||
|
||||
switch (mode) {
|
||||
case CAN_MODE_START:
|
||||
kvaser_usb_unlink_tx_urbs(priv);
|
||||
|
||||
err = kvaser_usb_leaf_simple_cmd_async(priv, CMD_START_CHIP);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
priv->can.state = CAN_STATE_ERROR_ACTIVE;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
|
Loading…
Reference in New Issue
Block a user