summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernard Pidoux <bernard.f6bvp@gmail.com>2026-05-28 17:38:18 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-06-27 11:07:40 +0100
commit35ed67c5f66dcfba53a184263bafc7c5bd542558 (patch)
treeb1b59abd56bd0742c07704dc81f9b4bc24e16a95
parent25982d734933184ef8c9a5d8c6ce782321e23324 (diff)
downloadlinux-stable-35ed67c5f66dcfba53a184263bafc7c5bd542558.tar.gz
linux-stable-35ed67c5f66dcfba53a184263bafc7c5bd542558.zip
rose: disconnect orphaned STATE_2 sockets when device is gone
commit d4f4cf9f09a3f5fafa8f09110a7c1b5d10f2f261 upstream. When ax25stop brings down ROSE interfaces, sockets in ROSE_STATE_2 (awaiting CLEAR CONFIRM) whose device pointer is already NULL are not reached by rose_kill_by_device() and wait for T3 (up to 180s) before self-cleaning via rose_timer_expiry(). This keeps the rose module usecount at 1, blocking rmmod for the full T3 duration. In rose_heartbeat_expiry(), detect ROSE_STATE_2 sockets with no device, cancel T3, release the neighbour reference, and call rose_disconnect() + sock_set_flag(SOCK_DESTROY). The next heartbeat tick (<=5s) then destroys the socket via the existing ROSE_STATE_0/SOCK_DESTROY path, allowing clean module unload within 10s instead of up to 180s. Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--net/rose/rose_timer.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c
index d997d24ab081..aa3dd4ab4a49 100644
--- a/net/rose/rose_timer.c
+++ b/net/rose/rose_timer.c
@@ -139,6 +139,20 @@ static void rose_heartbeat_expiry(struct timer_list *t)
}
break;
+ case ROSE_STATE_2:
+ /* Device gone before CLEAR CONFIRM arrived: stop waiting for T3
+ * and disconnect now instead of blocking rmmod for up to 180s. */
+ if (!rose->device) {
+ rose_stop_timer(sk);
+ if (rose->neighbour) {
+ rose_neigh_put(rose->neighbour);
+ rose->neighbour = NULL;
+ }
+ rose_disconnect(sk, ENETDOWN, -1, -1);
+ sock_set_flag(sk, SOCK_DESTROY);
+ }
+ break;
+
case ROSE_STATE_3:
/*
* Check for the state of the receive buffer.