Commit 65e349f7 authored by Jakub Kicinski's avatar Jakub Kicinski

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

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

Marc Kleine-Budde says:

====================
pull-request: can 2022-12-07

The 1st patch is by Oliver Hartkopp and fixes a potential NULL pointer
deref found by syzbot in the AF_CAN protocol.

The next 2 patches are by Jiri Slaby and Max Staudt and add the
missing flush_work() before freeing the underlying memory in the slcan
and can327 driver.

The last patch is by Frank Jungclaus and target the esd_usb driver and
fixes the CAN error counters, allowing them to return to zero.

* tag 'linux-can-fixes-for-6.1-20221207' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can:
  can: esd_usb: Allow REC and TEC to return to zero
  can: can327: flush TX_work on ldisc .close()
  can: slcan: fix freed work crash
  can: af_can: fix NULL pointer dereference in can_rcv_filter
====================

Link: https://lore.kernel.org/r/20221207105243.2483884-1-mkl@pengutronix.deSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 87a39882 918ee491
...@@ -796,9 +796,9 @@ static int can327_netdev_close(struct net_device *dev) ...@@ -796,9 +796,9 @@ static int can327_netdev_close(struct net_device *dev)
netif_stop_queue(dev); netif_stop_queue(dev);
/* Give UART one final chance to flush. */ /* We don't flush the UART TX queue here, as we want final stop
clear_bit(TTY_DO_WRITE_WAKEUP, &elm->tty->flags); * commands (like the above dummy char) to be flushed out.
flush_work(&elm->tx_work); */
can_rx_offload_disable(&elm->offload); can_rx_offload_disable(&elm->offload);
elm->can.state = CAN_STATE_STOPPED; elm->can.state = CAN_STATE_STOPPED;
...@@ -1069,12 +1069,15 @@ static void can327_ldisc_close(struct tty_struct *tty) ...@@ -1069,12 +1069,15 @@ static void can327_ldisc_close(struct tty_struct *tty)
{ {
struct can327 *elm = (struct can327 *)tty->disc_data; struct can327 *elm = (struct can327 *)tty->disc_data;
/* unregister_netdev() calls .ndo_stop() so we don't have to. /* unregister_netdev() calls .ndo_stop() so we don't have to. */
* Our .ndo_stop() also flushes the TTY write wakeup handler,
* so we can safely set elm->tty = NULL after this.
*/
unregister_candev(elm->dev); unregister_candev(elm->dev);
/* Give UART one final chance to flush.
* No need to clear TTY_DO_WRITE_WAKEUP since .write_wakeup() is
* serialised against .close() and will not be called once we return.
*/
flush_work(&elm->tx_work);
/* Mark channel as dead */ /* Mark channel as dead */
spin_lock_bh(&elm->lock); spin_lock_bh(&elm->lock);
tty->disc_data = NULL; tty->disc_data = NULL;
......
...@@ -864,12 +864,14 @@ static void slcan_close(struct tty_struct *tty) ...@@ -864,12 +864,14 @@ static void slcan_close(struct tty_struct *tty)
{ {
struct slcan *sl = (struct slcan *)tty->disc_data; struct slcan *sl = (struct slcan *)tty->disc_data;
/* unregister_netdev() calls .ndo_stop() so we don't have to.
* Our .ndo_stop() also flushes the TTY write wakeup handler,
* so we can safely set sl->tty = NULL after this.
*/
unregister_candev(sl->dev); unregister_candev(sl->dev);
/*
* The netdev needn't be UP (so .ndo_stop() is not called). Hence make
* sure this is not running before freeing it up.
*/
flush_work(&sl->tx_work);
/* Mark channel as dead */ /* Mark channel as dead */
spin_lock_bh(&sl->lock); spin_lock_bh(&sl->lock);
tty->disc_data = NULL; tty->disc_data = NULL;
......
...@@ -234,6 +234,10 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv, ...@@ -234,6 +234,10 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv,
u8 rxerr = msg->msg.rx.data[2]; u8 rxerr = msg->msg.rx.data[2];
u8 txerr = msg->msg.rx.data[3]; u8 txerr = msg->msg.rx.data[3];
netdev_dbg(priv->netdev,
"CAN_ERR_EV_EXT: dlc=%#02x state=%02x ecc=%02x rec=%02x tec=%02x\n",
msg->msg.rx.dlc, state, ecc, rxerr, txerr);
skb = alloc_can_err_skb(priv->netdev, &cf); skb = alloc_can_err_skb(priv->netdev, &cf);
if (skb == NULL) { if (skb == NULL) {
stats->rx_dropped++; stats->rx_dropped++;
...@@ -260,6 +264,8 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv, ...@@ -260,6 +264,8 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv,
break; break;
default: default:
priv->can.state = CAN_STATE_ERROR_ACTIVE; priv->can.state = CAN_STATE_ERROR_ACTIVE;
txerr = 0;
rxerr = 0;
break; break;
} }
} else { } else {
......
...@@ -677,7 +677,7 @@ static void can_receive(struct sk_buff *skb, struct net_device *dev) ...@@ -677,7 +677,7 @@ static void can_receive(struct sk_buff *skb, struct net_device *dev)
static int can_rcv(struct sk_buff *skb, struct net_device *dev, static int can_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev) struct packet_type *pt, struct net_device *orig_dev)
{ {
if (unlikely(dev->type != ARPHRD_CAN || (!can_is_can_skb(skb)))) { if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || !can_is_can_skb(skb))) {
pr_warn_once("PF_CAN: dropped non conform CAN skbuff: dev type %d, len %d\n", pr_warn_once("PF_CAN: dropped non conform CAN skbuff: dev type %d, len %d\n",
dev->type, skb->len); dev->type, skb->len);
...@@ -692,7 +692,7 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -692,7 +692,7 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev,
static int canfd_rcv(struct sk_buff *skb, struct net_device *dev, static int canfd_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev) struct packet_type *pt, struct net_device *orig_dev)
{ {
if (unlikely(dev->type != ARPHRD_CAN || (!can_is_canfd_skb(skb)))) { if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || !can_is_canfd_skb(skb))) {
pr_warn_once("PF_CAN: dropped non conform CAN FD skbuff: dev type %d, len %d\n", pr_warn_once("PF_CAN: dropped non conform CAN FD skbuff: dev type %d, len %d\n",
dev->type, skb->len); dev->type, skb->len);
...@@ -707,7 +707,7 @@ static int canfd_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -707,7 +707,7 @@ static int canfd_rcv(struct sk_buff *skb, struct net_device *dev,
static int canxl_rcv(struct sk_buff *skb, struct net_device *dev, static int canxl_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev) struct packet_type *pt, struct net_device *orig_dev)
{ {
if (unlikely(dev->type != ARPHRD_CAN || (!can_is_canxl_skb(skb)))) { if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || !can_is_canxl_skb(skb))) {
pr_warn_once("PF_CAN: dropped non conform CAN XL skbuff: dev type %d, len %d\n", pr_warn_once("PF_CAN: dropped non conform CAN XL skbuff: dev type %d, len %d\n",
dev->type, skb->len); dev->type, skb->len);
......
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