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
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
CONFIG_CAN=m
|
||||
CONFIG_CAN_DEV=m
|
||||
CONFIG_CAN_VCAN=m
|
Loading…
Reference in New Issue