mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 06:29:06 -04:00
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:
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user