On 07.06.2022 11:47:51, Dario Binacchi wrote: > It extends the protocol to receive the adapter CAN communication errors > and forward them to the netdev upper levels. > > Signed-off-by: Dario Binacchi <dario.binacchi@xxxxxxxxxxxxxxxxxxxx> > --- > > drivers/net/can/slcan/slcan-core.c | 104 ++++++++++++++++++++++++++++- > 1 file changed, 103 insertions(+), 1 deletion(-) > > diff --git a/drivers/net/can/slcan/slcan-core.c b/drivers/net/can/slcan/slcan-core.c > index b813a59534a3..02e7c14de45c 100644 > --- a/drivers/net/can/slcan/slcan-core.c > +++ b/drivers/net/can/slcan/slcan-core.c > @@ -182,8 +182,92 @@ int slcan_enable_err_rst_on_open(struct net_device *ndev, bool on) > * STANDARD SLCAN DECAPSULATION * > ************************************************************************/ > > +static void slc_bump_err(struct slcan *sl) > +{ > + struct net_device *dev = sl->dev; > + struct sk_buff *skb; > + struct can_frame *cf; > + char *cmd = sl->rbuff; > + bool rx_errors = false, tx_errors = false; > + int i, len; > + > + if (*cmd != 'e') > + return; > + > + cmd += SLC_CMD_LEN; > + /* get len from sanitized ASCII value */ What happens is a malicious device sends a wrong len value, that's longer than the RX'ed data? > + len = *cmd++; > + if (len >= '0' && len < '9') > + len -= '0'; > + else > + return; > + > + skb = alloc_can_err_skb(dev, &cf); Please continue error handling, even if no skb can be allocated. > + if (unlikely(!skb)) > + return; > + > + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; > + for (i = 0; i < len; i++, cmd++) { > + switch (*cmd) { > + case 'a': > + netdev_dbg(dev, "ACK error\n"); > + cf->can_id |= CAN_ERR_ACK; > + cf->data[3] = CAN_ERR_PROT_LOC_ACK; > + tx_errors = true; > + break; > + case 'b': > + netdev_dbg(dev, "Bit0 error\n"); > + cf->data[2] |= CAN_ERR_PROT_BIT0; > + tx_errors = true; > + break; > + case 'B': > + netdev_dbg(dev, "Bit1 error\n"); > + cf->data[2] |= CAN_ERR_PROT_BIT1; > + tx_errors = true; > + break; > + case 'c': > + netdev_dbg(dev, "CRC error\n"); > + cf->data[2] |= CAN_ERR_PROT_BIT; > + cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ; > + rx_errors = true; > + break; > + case 'f': > + netdev_dbg(dev, "Form Error\n"); > + cf->data[2] |= CAN_ERR_PROT_FORM; > + rx_errors = true; > + break; > + case 'o': > + netdev_dbg(dev, "Rx overrun error\n"); > + cf->can_id |= CAN_ERR_CRTL; > + cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; > + dev->stats.rx_over_errors++; > + dev->stats.rx_errors++; > + break; > + case 'O': > + netdev_dbg(dev, "Tx overrun error\n"); > + cf->can_id |= CAN_ERR_CRTL; > + cf->data[1] = CAN_ERR_CRTL_TX_OVERFLOW; > + dev->stats.tx_errors++; > + break; > + case 's': > + netdev_dbg(dev, "Stuff error\n"); > + cf->data[2] |= CAN_ERR_PROT_STUFF; > + rx_errors = true; > + break; > + } > + } > + > + if (rx_errors) > + dev->stats.rx_errors++; > + > + if (tx_errors) > + dev->stats.tx_errors++; > + > + netif_rx(skb); > +} > + Marc -- Pengutronix e.K. | Marc Kleine-Budde | Embedded Linux | https://www.pengutronix.de | Vertretung West/Dortmund | Phone: +49-231-2826-924 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
Attachment:
signature.asc
Description: PGP signature