From: Tetsuo Handa penguin-kernel@I-love.SAKURA.ne.jp
[ Upstream commit 5d5602236f5db19e8b337a2cd87a90ace5ea776d ]
syzbot is still reporting
unregister_netdevice: waiting for vcan0 to become free. Usage count = 2
even after commit 93a27b5891b8 ("can: j1939: add missing calls in NETDEV_UNREGISTER notification handler") was added. A debug printk() patch found that j1939_session_activate() can succeed even after j1939_cancel_active_session() from j1939_netdev_notify(NETDEV_UNREGISTER) has completed.
Since j1939_cancel_active_session() is processed with the session list lock held, checking ndev->reg_state in j1939_session_activate() with the session list lock held can reliably close the race window.
Reported-by: syzbot syzbot+881d65229ca4f9ae8c84@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=881d65229ca4f9ae8c84 Signed-off-by: Tetsuo Handa penguin-kernel@I-love.SAKURA.ne.jp Acked-by: Oleksij Rempel o.rempel@pengutronix.de Link: https://patch.msgid.link/b9653191-d479-4c8b-8536-1326d028db5c@I-love.SAKURA.... Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de Signed-off-by: Sasha Levin sashal@kernel.org ---
LLM Generated explanations, may be completely bogus:
---
## FINAL ANALYSIS SUMMARY
### What the commit fixes: A race condition in the CAN J1939 protocol driver where `j1939_session_activate()` can succeed even after `j1939_cancel_active_session()` from the NETDEV_UNREGISTER handler has completed. This leaves orphaned sessions with references to devices being unregistered, causing the "waiting for device to become free" hang.
### Why it matters to stable users: - **System hang**: The bug can cause network device unregistration to hang indefinitely - **Syzbot reproducible**: The bug was found by automated fuzzing, meaning it's triggerable in practice - **CAN J1939 users**: Affects automotive and industrial systems using the CAN J1939 protocol
### Stable kernel rule compliance:
| Criterion | Assessment | |-----------|------------| | Obviously correct | ✅ Yes - simple check using established kernel pattern | | Fixes real bug | ✅ Yes - syzbot-reported hang | | Small and contained | ✅ Yes - 2 lines added, 1 file changed | | No new features | ✅ Correct - only adds error path | | Tested | ✅ Has Acked-by from maintainer |
### Risk assessment: - **Very low risk**: The change only adds a conditional check before adding a session to the active list - **Uses established pattern**: `dev->reg_state != NETREG_REGISTERED` is used throughout net/can/raw.c and other networking code - **Cannot break existing functionality**: Adds a new error return path that's already properly handled (callers handle error returns)
### Dependencies: - The fix is logically independent - it adds a safety check that works regardless of other commits - The related commit 93a27b5891b8 is about a different part of the fix (adding missing calls in the unregister handler) - Both commits are improvements to the same underlying issue but can be applied separately
### Conclusion: This is a textbook example of a good stable backport candidate: 1. Fixes a real, user-visible bug (system hang) 2. Minimal change (2 lines) 3. Uses established kernel patterns 4. Has proper subsystem maintainer review 5. Low risk of regression
**YES**
net/can/j1939/transport.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c index fbf5c8001c9d..613a911dda10 100644 --- a/net/can/j1939/transport.c +++ b/net/can/j1939/transport.c @@ -1567,6 +1567,8 @@ int j1939_session_activate(struct j1939_session *session) if (active) { j1939_session_put(active); ret = -EAGAIN; + } else if (priv->ndev->reg_state != NETREG_REGISTERED) { + ret = -ENODEV; } else { WARN_ON_ONCE(session->state != J1939_SESSION_NEW); list_add_tail(&session->active_session_list_entry,