mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	linux-can-fixes-for-6.17-20250910
-----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEn/sM2K9nqF/8FWzzDHRl3/mQkZwFAmjBpO8THG1rbEBwZW5n dXRyb25peC5kZQAKCRAMdGXf+ZCRnJOOB/9r35uZBD1+ZZVpvoByhil8XY7K42Vv LrARJ8+kh1Q6mcuB4V/176GBPJ7JabSUTGqvqvYbJBAB5obONhLU5Bkb/7lM2z1G MOUe0DMiBP+J3K8zqXcEKhqeW0qQO6pqfnv8iIj97Kxwd5JRPJq8pMpCIC/RLzOY Ot7+fcsE+cSZt9VumnQTx/S1fzGoY1C9VCglSr9B0O6IiTZZBIPNg8EwIGvbm7oh uofnFRocRZaWQ6OErdRSTLK4hu11DeFUmEAA6YN2ikpAdshUsf3U8HYaz2LIEEuu zGflFXrMekXqDod1SvhklLPUY/ssC11dUon+4Cgz/yK6I+lFvD/cuLIP =/YxL -----END PGP SIGNATURE----- Merge tag 'linux-can-fixes-for-6.17-20250910' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can Marc Kleine-Budde says: ==================== pull-request: can 2025-09-10 The 1st patch is by Alex Tran and fixes the Documentation of the struct bcm_msg_head. Davide Caratti's patch enabled the VCAN driver as a module for the Linux self tests. Tetsuo Handa contributes 3 patches that fix various problems in the CAN j1939 protocol. Anssi Hannula's patch fixes a potential use-after-free in the xilinx_can driver. Geert Uytterhoeven's patch fixes the rcan_can's suspend to RAM on R-Car Gen3 using PSCI. * tag 'linux-can-fixes-for-6.17-20250910' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can: can: rcar_can: rcar_can_resume(): fix s2ram with PSCI can: xilinx_can: xcan_write_frame(): fix use-after-free of transmitted SKB can: j1939: j1939_local_ecu_get(): undo increment when j1939_local_ecu_get() fails can: j1939: j1939_sk_bind(): call j1939_priv_put() immediately when j1939_local_ecu_get() failed can: j1939: implement NETDEV_UNREGISTER notification handler selftests: can: enable CONFIG_CAN_VCAN as a module docs: networking: can: change bcm_msg_head frames member to support flexible array ==================== Link: https://patch.msgid.link/20250910162907.948454-1-mkl@pengutronix.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
		
						commit
						ccf78f7f05
					
				
					 8 changed files with 73 additions and 17 deletions
				
			
		| 
						 | 
				
			
			@ -742,7 +742,7 @@ The broadcast manager sends responses to user space in the same form:
 | 
			
		|||
            struct timeval ival1, ival2;    /* count and subsequent interval */
 | 
			
		||||
            canid_t can_id;                 /* unique can_id for task */
 | 
			
		||||
            __u32 nframes;                  /* number of can_frames following */
 | 
			
		||||
            struct can_frame frames[0];
 | 
			
		||||
            struct can_frame frames[];
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
The aligned payload 'frames' uses the same basic CAN frame structure defined
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -861,7 +861,6 @@ static int rcar_can_resume(struct device *dev)
 | 
			
		|||
{
 | 
			
		||||
	struct net_device *ndev = dev_get_drvdata(dev);
 | 
			
		||||
	struct rcar_can_priv *priv = netdev_priv(ndev);
 | 
			
		||||
	u16 ctlr;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	if (!netif_running(ndev))
 | 
			
		||||
| 
						 | 
				
			
			@ -873,12 +872,7 @@ static int rcar_can_resume(struct device *dev)
 | 
			
		|||
		return err;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctlr = readw(&priv->regs->ctlr);
 | 
			
		||||
	ctlr &= ~RCAR_CAN_CTLR_SLPM;
 | 
			
		||||
	writew(ctlr, &priv->regs->ctlr);
 | 
			
		||||
	ctlr &= ~RCAR_CAN_CTLR_CANM;
 | 
			
		||||
	writew(ctlr, &priv->regs->ctlr);
 | 
			
		||||
	priv->can.state = CAN_STATE_ERROR_ACTIVE;
 | 
			
		||||
	rcar_can_start(ndev);
 | 
			
		||||
 | 
			
		||||
	netif_device_attach(ndev);
 | 
			
		||||
	netif_start_queue(ndev);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -690,14 +690,6 @@ static void xcan_write_frame(struct net_device *ndev, struct sk_buff *skb,
 | 
			
		|||
		dlc |= XCAN_DLCR_EDL_MASK;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(priv->devtype.flags & XCAN_FLAG_TX_MAILBOXES) &&
 | 
			
		||||
	    (priv->devtype.flags & XCAN_FLAG_TXFEMP))
 | 
			
		||||
		can_put_echo_skb(skb, ndev, priv->tx_head % priv->tx_max, 0);
 | 
			
		||||
	else
 | 
			
		||||
		can_put_echo_skb(skb, ndev, 0, 0);
 | 
			
		||||
 | 
			
		||||
	priv->tx_head++;
 | 
			
		||||
 | 
			
		||||
	priv->write_reg(priv, XCAN_FRAME_ID_OFFSET(frame_offset), id);
 | 
			
		||||
	/* If the CAN frame is RTR frame this write triggers transmission
 | 
			
		||||
	 * (not on CAN FD)
 | 
			
		||||
| 
						 | 
				
			
			@ -730,6 +722,14 @@ static void xcan_write_frame(struct net_device *ndev, struct sk_buff *skb,
 | 
			
		|||
					data[1]);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(priv->devtype.flags & XCAN_FLAG_TX_MAILBOXES) &&
 | 
			
		||||
	    (priv->devtype.flags & XCAN_FLAG_TXFEMP))
 | 
			
		||||
		can_put_echo_skb(skb, ndev, priv->tx_head % priv->tx_max, 0);
 | 
			
		||||
	else
 | 
			
		||||
		can_put_echo_skb(skb, ndev, 0, 0);
 | 
			
		||||
 | 
			
		||||
	priv->tx_head++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -290,8 +290,11 @@ int j1939_local_ecu_get(struct j1939_priv *priv, name_t name, u8 sa)
 | 
			
		|||
	if (!ecu)
 | 
			
		||||
		ecu = j1939_ecu_create_locked(priv, name);
 | 
			
		||||
	err = PTR_ERR_OR_ZERO(ecu);
 | 
			
		||||
	if (err)
 | 
			
		||||
	if (err) {
 | 
			
		||||
		if (j1939_address_is_unicast(sa))
 | 
			
		||||
			priv->ents[sa].nusers--;
 | 
			
		||||
		goto done;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ecu->nusers++;
 | 
			
		||||
	/* TODO: do we care if ecu->addr != sa? */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -212,6 +212,7 @@ void j1939_priv_get(struct j1939_priv *priv);
 | 
			
		|||
 | 
			
		||||
/* notify/alert all j1939 sockets bound to ifindex */
 | 
			
		||||
void j1939_sk_netdev_event_netdown(struct j1939_priv *priv);
 | 
			
		||||
void j1939_sk_netdev_event_unregister(struct j1939_priv *priv);
 | 
			
		||||
int j1939_cancel_active_session(struct j1939_priv *priv, struct sock *sk);
 | 
			
		||||
void j1939_tp_init(struct j1939_priv *priv);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -377,6 +377,9 @@ static int j1939_netdev_notify(struct notifier_block *nb,
 | 
			
		|||
		j1939_sk_netdev_event_netdown(priv);
 | 
			
		||||
		j1939_ecu_unmap_all(priv);
 | 
			
		||||
		break;
 | 
			
		||||
	case NETDEV_UNREGISTER:
 | 
			
		||||
		j1939_sk_netdev_event_unregister(priv);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	j1939_priv_put(priv);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -521,6 +521,9 @@ static int j1939_sk_bind(struct socket *sock, struct sockaddr *uaddr, int len)
 | 
			
		|||
	ret = j1939_local_ecu_get(priv, jsk->addr.src_name, jsk->addr.sa);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		j1939_netdev_stop(priv);
 | 
			
		||||
		jsk->priv = NULL;
 | 
			
		||||
		synchronize_rcu();
 | 
			
		||||
		j1939_priv_put(priv);
 | 
			
		||||
		goto out_release_sock;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1300,6 +1303,55 @@ void j1939_sk_netdev_event_netdown(struct j1939_priv *priv)
 | 
			
		|||
	read_unlock_bh(&priv->j1939_socks_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void j1939_sk_netdev_event_unregister(struct j1939_priv *priv)
 | 
			
		||||
{
 | 
			
		||||
	struct sock *sk;
 | 
			
		||||
	struct j1939_sock *jsk;
 | 
			
		||||
	bool wait_rcu = false;
 | 
			
		||||
 | 
			
		||||
rescan: /* The caller is holding a ref on this "priv" via j1939_priv_get_by_ndev(). */
 | 
			
		||||
	read_lock_bh(&priv->j1939_socks_lock);
 | 
			
		||||
	list_for_each_entry(jsk, &priv->j1939_socks, list) {
 | 
			
		||||
		/* Skip if j1939_jsk_add() is not called on this socket. */
 | 
			
		||||
		if (!(jsk->state & J1939_SOCK_BOUND))
 | 
			
		||||
			continue;
 | 
			
		||||
		sk = &jsk->sk;
 | 
			
		||||
		sock_hold(sk);
 | 
			
		||||
		read_unlock_bh(&priv->j1939_socks_lock);
 | 
			
		||||
		/* Check if j1939_jsk_del() is not yet called on this socket after holding
 | 
			
		||||
		 * socket's lock, for both j1939_sk_bind() and j1939_sk_release() call
 | 
			
		||||
		 * j1939_jsk_del() with socket's lock held.
 | 
			
		||||
		 */
 | 
			
		||||
		lock_sock(sk);
 | 
			
		||||
		if (jsk->state & J1939_SOCK_BOUND) {
 | 
			
		||||
			/* Neither j1939_sk_bind() nor j1939_sk_release() called j1939_jsk_del().
 | 
			
		||||
			 * Make this socket no longer bound, by pretending as if j1939_sk_bind()
 | 
			
		||||
			 * dropped old references but did not get new references.
 | 
			
		||||
			 */
 | 
			
		||||
			j1939_jsk_del(priv, jsk);
 | 
			
		||||
			j1939_local_ecu_put(priv, jsk->addr.src_name, jsk->addr.sa);
 | 
			
		||||
			j1939_netdev_stop(priv);
 | 
			
		||||
			/* Call j1939_priv_put() now and prevent j1939_sk_sock_destruct() from
 | 
			
		||||
			 * calling the corresponding j1939_priv_put().
 | 
			
		||||
			 *
 | 
			
		||||
			 * j1939_sk_sock_destruct() is supposed to call j1939_priv_put() after
 | 
			
		||||
			 * an RCU grace period. But since the caller is holding a ref on this
 | 
			
		||||
			 * "priv", we can defer synchronize_rcu() until immediately before
 | 
			
		||||
			 * the caller calls j1939_priv_put().
 | 
			
		||||
			 */
 | 
			
		||||
			j1939_priv_put(priv);
 | 
			
		||||
			jsk->priv = NULL;
 | 
			
		||||
			wait_rcu = true;
 | 
			
		||||
		}
 | 
			
		||||
		release_sock(sk);
 | 
			
		||||
		sock_put(sk);
 | 
			
		||||
		goto rescan;
 | 
			
		||||
	}
 | 
			
		||||
	read_unlock_bh(&priv->j1939_socks_lock);
 | 
			
		||||
	if (wait_rcu)
 | 
			
		||||
		synchronize_rcu();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int j1939_sk_no_ioctlcmd(struct socket *sock, unsigned int cmd,
 | 
			
		||||
				unsigned long arg)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										3
									
								
								tools/testing/selftests/net/can/config
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								tools/testing/selftests/net/can/config
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
CONFIG_CAN=m
 | 
			
		||||
CONFIG_CAN_DEV=m
 | 
			
		||||
CONFIG_CAN_VCAN=m
 | 
			
		||||
		Loading…
	
		Reference in a new issue