diff options
| author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2025-11-25 22:39:59 +0900 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2026-01-17 16:30:01 +0100 |
| commit | 78d87b72cebe2a993fd5b017e9f14fb6278f2eae (patch) | |
| tree | dd3778330fc01f961cab8adb38e00c0fcfab3e7f | |
| parent | f73d92997388b7b50b15b4ac82c5ba0dec138559 (diff) | |
can: j1939: make j1939_session_activate() fail if device is no longer registered
[ 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.ne.jp
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
| -rw-r--r-- | net/can/j1939/transport.c | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c index 9b72d118d756..1186326b0f2e 100644 --- a/net/can/j1939/transport.c +++ b/net/can/j1939/transport.c @@ -1571,6 +1571,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, |
