Skip to content

Commit 743d176

Browse files
dhowellsdavem330
authored andcommitted
rxrpc: Fix I/O thread stop
The rxrpc I/O thread checks to see if there's any work it needs to do, and if not, checks kthread_should_stop() before scheduling, and if it should stop, breaks out of the loop and tries to clean up and exit. This can, however, race with socket destruction, wherein outstanding calls are aborted and released from the socket and then the socket unuses the local endpoint, causing kthread_stop() to be issued. The abort is deferred to the I/O thread and the event can by issued between the I/O thread checking if there's any work to be done (such as processing call aborts) and the stop being seen. This results in the I/O thread stopping processing of events whilst call cleanup events are still outstanding, leading to connections or other objects still being around and uncleaned up, which can result in assertions being triggered, e.g.: rxrpc: AF_RXRPC: Leaked client conn 00000000e8009865 {2} ------------[ cut here ]------------ kernel BUG at net/rxrpc/conn_client.c:64! Fix this by retrieving the kthread_should_stop() indication, then checking to see if there's more work to do, and going back round the loop if there is, and breaking out of the loop only if there wasn't. This was triggered by a syzbot test that produced some other symptom[1]. Fixes: a275da6 ("rxrpc: Create a per-local endpoint receive queue and I/O thread") Signed-off-by: David Howells <[email protected]> cc: Marc Dionne <[email protected]> cc: [email protected] Link: https://lore.kernel.org/r/[email protected]/ [1] Signed-off-by: David S. Miller <[email protected]>
1 parent c838f1a commit 743d176

File tree

1 file changed

+3
-1
lines changed

1 file changed

+3
-1
lines changed

net/rxrpc/io_thread.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@ int rxrpc_io_thread(void *data)
425425
struct rxrpc_local *local = data;
426426
struct rxrpc_call *call;
427427
struct sk_buff *skb;
428+
bool should_stop;
428429

429430
complete(&local->io_thread_ready);
430431

@@ -478,13 +479,14 @@ int rxrpc_io_thread(void *data)
478479
}
479480

480481
set_current_state(TASK_INTERRUPTIBLE);
482+
should_stop = kthread_should_stop();
481483
if (!skb_queue_empty(&local->rx_queue) ||
482484
!list_empty(&local->call_attend_q)) {
483485
__set_current_state(TASK_RUNNING);
484486
continue;
485487
}
486488

487-
if (kthread_should_stop())
489+
if (should_stop)
488490
break;
489491
schedule();
490492
}

0 commit comments

Comments
 (0)