Merge patch series "can: j1939: resend lost patches for buffer init and netdevice tracking"

Oleksij Rempel <o.rempel@pengutronix.de> says:

This series collects and resends two j1939 patches that were previously
lost on their way upstream. They address different, unconnected issues in
the stack:

- Patch 1 prevents residual data leaks by zeroing the allocated receive
  buffer in j1939_session_fresh_new().
- Patch 2 implements netdevice_tracker for j1939_{priv,session,ecu}
  management to help investigate a dev_hold()/dev_put() refcount
  leak (unregister_netdevice() waiting for vcan0) reported by syzbot.

Link: https://patch.msgid.link/20260728055835.1151785-1-o.rempel@pengutronix.de
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
This commit is contained in:
Marc Kleine-Budde
2026-07-29 10:16:00 +02:00
4 changed files with 12 additions and 5 deletions

View File

@@ -20,6 +20,7 @@ static void __j1939_ecu_release(struct kref *kref)
struct j1939_priv *priv = ecu->priv;
list_del(&ecu->list);
netdev_put(priv->ndev, &ecu->priv_dev_tracker);
kfree(ecu);
j1939_priv_put(priv);
}
@@ -155,6 +156,7 @@ struct j1939_ecu *j1939_ecu_create_locked(struct j1939_priv *priv, name_t name)
if (!ecu)
return ERR_PTR(-ENOMEM);
kref_init(&ecu->kref);
netdev_hold(priv->ndev, &ecu->priv_dev_tracker, gfp_any());
ecu->addr = J1939_IDLE_ADDR;
ecu->name = name;

View File

@@ -38,6 +38,7 @@ struct j1939_ecu {
struct hrtimer ac_timer;
struct kref kref;
struct j1939_priv *priv;
netdevice_tracker priv_dev_tracker;
/* count users, to help transport protocol decide for interaction */
int nusers;
@@ -60,6 +61,7 @@ struct j1939_priv {
rwlock_t lock;
struct net_device *ndev;
netdevice_tracker dev_tracker;
/* list of 256 ecu ptrs, that cache the claimed addresses.
* also protected by the above lock
@@ -230,6 +232,7 @@ enum j1939_session_state {
struct j1939_session {
struct j1939_priv *priv;
netdevice_tracker priv_dev_tracker;
struct list_head active_session_list_entry;
struct list_head sk_session_queue_entry;
struct kref kref;

View File

@@ -137,7 +137,7 @@ static struct j1939_priv *j1939_priv_create(struct net_device *ndev)
priv->ndev = ndev;
kref_init(&priv->kref);
kref_init(&priv->rx_kref);
dev_hold(ndev);
netdev_hold(ndev, &priv->dev_tracker, GFP_KERNEL);
netdev_dbg(priv->ndev, "%s : 0x%p\n", __func__, priv);
@@ -163,7 +163,7 @@ static void __j1939_priv_release(struct kref *kref)
WARN_ON_ONCE(!list_empty(&priv->ecus));
WARN_ON_ONCE(!list_empty(&priv->j1939_socks));
dev_put(ndev);
netdev_put(ndev, &priv->dev_tracker);
kfree(priv);
}
@@ -281,7 +281,7 @@ struct j1939_priv *j1939_netdev_start(struct net_device *ndev)
*/
kref_get(&priv_new->rx_kref);
mutex_unlock(&j1939_netdev_lock);
dev_put(ndev);
netdev_put(ndev, &priv->dev_tracker);
kfree(priv);
return priv_new;
}
@@ -298,7 +298,7 @@ struct j1939_priv *j1939_netdev_start(struct net_device *ndev)
j1939_priv_set(ndev, NULL);
mutex_unlock(&j1939_netdev_lock);
dev_put(ndev);
netdev_put(ndev, &priv->dev_tracker);
kfree(priv);
return ERR_PTR(ret);

View File

@@ -283,6 +283,7 @@ static void j1939_session_destroy(struct j1939_session *session)
kfree_skb(skb);
}
__j1939_session_drop(session);
netdev_put(session->priv->ndev, &session->priv_dev_tracker);
j1939_priv_put(session->priv);
kfree(session);
}
@@ -1526,6 +1527,7 @@ static struct j1939_session *j1939_session_new(struct j1939_priv *priv,
INIT_LIST_HEAD(&session->active_session_list_entry);
INIT_LIST_HEAD(&session->sk_session_queue_entry);
kref_init(&session->kref);
netdev_hold(priv->ndev, &session->priv_dev_tracker, gfp_any());
j1939_priv_get(priv);
session->priv = priv;
@@ -1579,7 +1581,7 @@ j1939_session *j1939_session_fresh_new(struct j1939_priv *priv,
}
/* alloc data area */
skb_put(skb, size);
skb_put_zero(skb, size);
/* skb is recounted in j1939_session_new() */
return session;
}