Re: [PATCH v3.2] can: j1939: fix j1939_ecu refcount leak

From: Karl Mehltretter

Date: Mon Oct 26 2026 - 23:31:26 EST


> list_for_each_entry(ecu, &priv->ecus, list) {
> - if (ecu->name == name)
> + if (ecu->name == name && j1939_ecu_valid(ecu))
> return ecu;

This also hides a live, named ECU from j1939_local_ecu_put() during
unregister. The netdev core sets reg_state to NETREG_UNREGISTERING before
issuing NETDEV_UNREGISTER, so j1939_ecu_valid() is false when a bound
socket reaches this cleanup path:

j1939_netdev_notifier()
j1939_sk_netdev_event_unregister()
j1939_local_ecu_put()
j1939_ecu_find_by_name_locked()


The lookup then returns NULL. j1939_local_ecu_put() warns and returns
without dropping the socket's ECU reference. That keeps the ECU's netdev
and j1939_priv references alive, preventing netdev_wait_allrefs_any()
from completing.

This is based on source review with AI assistance. I have not reproduced
the unregister hang at runtime.

Could teardown use a lookup that permits NETREG_UNREGISTERING and a dead
rx_kref, while retaining the nonzero ecu->kref check? The registration
and receive-lifetime restrictions are needed when acquiring new users,
but cleanup must still find the ECU whose reference it owns.

The ecu->kref check remains necessary because zero-reference entries stay on
the list until the RCU callback removes them.

Thanks,
Karl