Message ID | 20220607094752.1029295-13-dario.binacchi@amarulasolutions.com |
---|---|
State | New |
Headers | show |
Series |
|
Related | show |
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@amarulasolutions.com> > --- > > 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
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 */ + len = *cmd++; + if (len >= '0' && len < '9') + len -= '0'; + else + return; + + skb = alloc_can_err_skb(dev, &cf); + 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); +} + /* Send one completely decapsulated can_frame to the network layer */ -static void slc_bump(struct slcan *sl) +static void slc_bump_frame(struct slcan *sl) { struct sk_buff *skb; struct can_frame cf, *scf; @@ -257,6 +341,24 @@ static void slc_bump(struct slcan *sl) netif_rx(skb); } +static void slc_bump(struct slcan *sl) +{ + switch (sl->rbuff[0]) { + case 'r': + fallthrough; + case 't': + fallthrough; + case 'R': + fallthrough; + case 'T': + return slc_bump_frame(sl); + case 'e': + return slc_bump_err(sl); + default: + return; + } +} + /* parse tty input stream */ static void slcan_unesc(struct slcan *sl, unsigned char s) {
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@amarulasolutions.com> --- drivers/net/can/slcan/slcan-core.c | 104 ++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-)