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

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.de


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 87a39882 918ee491
Loading
Loading
Loading
Loading
+10 −7
Original line number Diff line number Diff line
@@ -796,9 +796,9 @@ static int can327_netdev_close(struct net_device *dev)

	netif_stop_queue(dev);

	/* Give UART one final chance to flush. */
	clear_bit(TTY_DO_WRITE_WAKEUP, &elm->tty->flags);
	flush_work(&elm->tx_work);
	/* We don't flush the UART TX queue here, as we want final stop
	 * commands (like the above dummy char) to be flushed out.
	 */

	can_rx_offload_disable(&elm->offload);
	elm->can.state = CAN_STATE_STOPPED;
@@ -1069,12 +1069,15 @@ static void can327_ldisc_close(struct tty_struct *tty)
{
	struct can327 *elm = (struct can327 *)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 elm->tty = NULL after this.
	 */
	/* unregister_netdev() calls .ndo_stop() so we don't have to. */
	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 */
	spin_lock_bh(&elm->lock);
	tty->disc_data = NULL;
+6 −4
Original line number Diff line number Diff line
@@ -864,12 +864,14 @@ static void slcan_close(struct tty_struct *tty)
{
	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);

	/*
	 * 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 */
	spin_lock_bh(&sl->lock);
	tty->disc_data = NULL;
+6 −0
Original line number Diff line number Diff line
@@ -234,6 +234,10 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv,
		u8 rxerr = msg->msg.rx.data[2];
		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);
		if (skb == NULL) {
			stats->rx_dropped++;
@@ -260,6 +264,8 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv,
				break;
			default:
				priv->can.state = CAN_STATE_ERROR_ACTIVE;
				txerr = 0;
				rxerr = 0;
				break;
			}
		} else {
+3 −3
Original line number Diff line number Diff line
@@ -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,
		   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",
			     dev->type, skb->len);

@@ -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,
		     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",
			     dev->type, skb->len);

@@ -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,
		     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",
			     dev->type, skb->len);