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:
Jakub Kicinski 2025-09-10 19:29:40 -07:00
commit ccf78f7f05
8 changed files with 73 additions and 17 deletions

View File

@ -742,7 +742,7 @@ The broadcast manager sends responses to user space in the same form:
struct timeval ival1, ival2; /* count and subsequent interval */ struct timeval ival1, ival2; /* count and subsequent interval */
canid_t can_id; /* unique can_id for task */ canid_t can_id; /* unique can_id for task */
__u32 nframes; /* number of can_frames following */ __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 The aligned payload 'frames' uses the same basic CAN frame structure defined

View File

@ -861,7 +861,6 @@ static int rcar_can_resume(struct device *dev)
{ {
struct net_device *ndev = dev_get_drvdata(dev); struct net_device *ndev = dev_get_drvdata(dev);
struct rcar_can_priv *priv = netdev_priv(ndev); struct rcar_can_priv *priv = netdev_priv(ndev);
u16 ctlr;
int err; int err;
if (!netif_running(ndev)) if (!netif_running(ndev))
@ -873,12 +872,7 @@ static int rcar_can_resume(struct device *dev)
return err; return err;
} }
ctlr = readw(&priv->regs->ctlr); rcar_can_start(ndev);
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;
netif_device_attach(ndev); netif_device_attach(ndev);
netif_start_queue(ndev); netif_start_queue(ndev);

View File

@ -690,14 +690,6 @@ static void xcan_write_frame(struct net_device *ndev, struct sk_buff *skb,
dlc |= XCAN_DLCR_EDL_MASK; 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); priv->write_reg(priv, XCAN_FRAME_ID_OFFSET(frame_offset), id);
/* If the CAN frame is RTR frame this write triggers transmission /* If the CAN frame is RTR frame this write triggers transmission
* (not on CAN FD) * (not on CAN FD)
@ -730,6 +722,14 @@ static void xcan_write_frame(struct net_device *ndev, struct sk_buff *skb,
data[1]); 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++;
} }
/** /**

View File

@ -290,8 +290,11 @@ int j1939_local_ecu_get(struct j1939_priv *priv, name_t name, u8 sa)
if (!ecu) if (!ecu)
ecu = j1939_ecu_create_locked(priv, name); ecu = j1939_ecu_create_locked(priv, name);
err = PTR_ERR_OR_ZERO(ecu); err = PTR_ERR_OR_ZERO(ecu);
if (err) if (err) {
if (j1939_address_is_unicast(sa))
priv->ents[sa].nusers--;
goto done; goto done;
}
ecu->nusers++; ecu->nusers++;
/* TODO: do we care if ecu->addr != sa? */ /* TODO: do we care if ecu->addr != sa? */

View File

@ -212,6 +212,7 @@ void j1939_priv_get(struct j1939_priv *priv);
/* notify/alert all j1939 sockets bound to ifindex */ /* notify/alert all j1939 sockets bound to ifindex */
void j1939_sk_netdev_event_netdown(struct j1939_priv *priv); 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); int j1939_cancel_active_session(struct j1939_priv *priv, struct sock *sk);
void j1939_tp_init(struct j1939_priv *priv); void j1939_tp_init(struct j1939_priv *priv);

View File

@ -377,6 +377,9 @@ static int j1939_netdev_notify(struct notifier_block *nb,
j1939_sk_netdev_event_netdown(priv); j1939_sk_netdev_event_netdown(priv);
j1939_ecu_unmap_all(priv); j1939_ecu_unmap_all(priv);
break; break;
case NETDEV_UNREGISTER:
j1939_sk_netdev_event_unregister(priv);
break;
} }
j1939_priv_put(priv); j1939_priv_put(priv);

View File

@ -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); ret = j1939_local_ecu_get(priv, jsk->addr.src_name, jsk->addr.sa);
if (ret) { if (ret) {
j1939_netdev_stop(priv); j1939_netdev_stop(priv);
jsk->priv = NULL;
synchronize_rcu();
j1939_priv_put(priv);
goto out_release_sock; 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); 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, static int j1939_sk_no_ioctlcmd(struct socket *sock, unsigned int cmd,
unsigned long arg) unsigned long arg)
{ {

View File

@ -0,0 +1,3 @@
CONFIG_CAN=m
CONFIG_CAN_DEV=m
CONFIG_CAN_VCAN=m