Skip to content

Commit 62c52f8

Browse files
committed
rxrpc: Fix I/O thread startup getting skipped
jira LE-1907 Rebuild_History Non-Buildable kernel-5.14.0-284.30.1.el9_2 commit-author David Howells <[email protected]> commit 8fbcc83 Empty-Commit: Cherry-Pick Conflicts during history rebuild. Will be included in final tarball splat. Ref for failed cherry-pick at: ciq/ciq_backports/kernel-5.14.0-284.30.1.el9_2/8fbcc833.failed When starting a kthread, the __kthread_create_on_node() function, as called from kthread_run(), waits for a completion to indicate that the task_struct (or failure state) of the new kernel thread is available before continuing. This does not wait, however, for the thread function to be invoked and, indeed, will skip it if kthread_stop() gets called before it gets there. If this happens, though, kthread_run() will have returned successfully, indicating that the thread was started and returning the task_struct pointer. The actual error indication is returned by kthread_stop(). Note that this is ambiguous, as the caller cannot tell whether the -EINTR error code came from kthread() or from the thread function. This was encountered in the new rxrpc I/O thread, where if the system is being pounded hard by, say, syzbot, the check of KTHREAD_SHOULD_STOP can be delayed long enough for kthread_stop() to get called when rxrpc releases a socket - and this causes an oops because the I/O thread function doesn't get started and thus doesn't remove the rxrpc_local struct from the local_endpoints list. Fix this by using a completion to wait for the thread to actually enter rxrpc_io_thread(). This makes sure the thread can't be prematurely stopped and makes sure the relied-upon cleanup is done. Fixes: a275da6 ("rxrpc: Create a per-local endpoint receive queue and I/O thread") Reported-by: [email protected] Signed-off-by: David Howells <[email protected]> cc: Marc Dionne <[email protected]> cc: Hillf Danton <[email protected]> Link: https://lore.kernel.org/r/[email protected]/ Signed-off-by: David S. Miller <[email protected]> (cherry picked from commit 8fbcc83) Signed-off-by: Jonathan Maple <[email protected]> # Conflicts: # net/rxrpc/ar-internal.h # net/rxrpc/io_thread.c # net/rxrpc/local_object.c
1 parent adf83af commit 62c52f8

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
rxrpc: Fix I/O thread startup getting skipped
2+
3+
jira LE-1907
4+
Rebuild_History Non-Buildable kernel-5.14.0-284.30.1.el9_2
5+
commit-author David Howells <[email protected]>
6+
commit 8fbcc83334a7b5b42b6bc1fae2458bf25eb57768
7+
Empty-Commit: Cherry-Pick Conflicts during history rebuild.
8+
Will be included in final tarball splat. Ref for failed cherry-pick at:
9+
ciq/ciq_backports/kernel-5.14.0-284.30.1.el9_2/8fbcc833.failed
10+
11+
When starting a kthread, the __kthread_create_on_node() function, as called
12+
from kthread_run(), waits for a completion to indicate that the task_struct
13+
(or failure state) of the new kernel thread is available before continuing.
14+
15+
This does not wait, however, for the thread function to be invoked and,
16+
indeed, will skip it if kthread_stop() gets called before it gets there.
17+
18+
If this happens, though, kthread_run() will have returned successfully,
19+
indicating that the thread was started and returning the task_struct
20+
pointer. The actual error indication is returned by kthread_stop().
21+
22+
Note that this is ambiguous, as the caller cannot tell whether the -EINTR
23+
error code came from kthread() or from the thread function.
24+
25+
This was encountered in the new rxrpc I/O thread, where if the system is
26+
being pounded hard by, say, syzbot, the check of KTHREAD_SHOULD_STOP can be
27+
delayed long enough for kthread_stop() to get called when rxrpc releases a
28+
socket - and this causes an oops because the I/O thread function doesn't
29+
get started and thus doesn't remove the rxrpc_local struct from the
30+
local_endpoints list.
31+
32+
Fix this by using a completion to wait for the thread to actually enter
33+
rxrpc_io_thread(). This makes sure the thread can't be prematurely
34+
stopped and makes sure the relied-upon cleanup is done.
35+
36+
Fixes: a275da62e8c1 ("rxrpc: Create a per-local endpoint receive queue and I/O thread")
37+
Reported-by: [email protected]
38+
Signed-off-by: David Howells <[email protected]>
39+
cc: Marc Dionne <[email protected]>
40+
cc: Hillf Danton <[email protected]>
41+
Link: https://lore.kernel.org/r/[email protected]/
42+
Signed-off-by: David S. Miller <[email protected]>
43+
(cherry picked from commit 8fbcc83334a7b5b42b6bc1fae2458bf25eb57768)
44+
Signed-off-by: Jonathan Maple <[email protected]>
45+
46+
# Conflicts:
47+
# net/rxrpc/ar-internal.h
48+
# net/rxrpc/io_thread.c
49+
# net/rxrpc/local_object.c
50+
diff --cc net/rxrpc/ar-internal.h
51+
index 46ce41afb431,37f3aec784cc..000000000000
52+
--- a/net/rxrpc/ar-internal.h
53+
+++ b/net/rxrpc/ar-internal.h
54+
@@@ -279,13 -286,12 +279,18 @@@ struct rxrpc_local
55+
struct rxrpc_net *rxnet; /* The network ns in which this resides */
56+
struct hlist_node link;
57+
struct socket *socket; /* my UDP socket */
58+
++<<<<<<< HEAD
59+
+ struct work_struct processor;
60+
+ struct list_head ack_tx_queue; /* List of ACKs that need sending */
61+
+ spinlock_t ack_tx_lock; /* ACK list lock */
62+
++=======
63+
+ struct task_struct *io_thread;
64+
+ struct completion io_thread_ready; /* Indication that the I/O thread started */
65+
++>>>>>>> 8fbcc83334a7 (rxrpc: Fix I/O thread startup getting skipped)
66+
struct rxrpc_sock __rcu *service; /* Service(s) listening on this endpoint */
67+
struct rw_semaphore defrag_sem; /* control re-enablement of IP DF bit */
68+
- struct sk_buff_head rx_queue; /* Received packets */
69+
- struct list_head call_attend_q; /* Calls requiring immediate attention */
70+
+ struct sk_buff_head reject_queue; /* packets awaiting rejection */
71+
+ struct sk_buff_head event_queue; /* endpoint event packets awaiting processing */
72+
struct rb_root client_bundles; /* Client connection bundles by socket params */
73+
spinlock_t client_bundles_lock; /* Lock for client_bundles */
74+
spinlock_t lock; /* access lock */
75+
diff --cc net/rxrpc/local_object.c
76+
index 846558613c7f,270b63d8f37a..000000000000
77+
--- a/net/rxrpc/local_object.c
78+
+++ b/net/rxrpc/local_object.c
79+
@@@ -83,12 -96,10 +83,18 @@@ static struct rxrpc_local *rxrpc_alloc_
80+
atomic_set(&local->active_users, 1);
81+
local->rxnet = rxnet;
82+
INIT_HLIST_NODE(&local->link);
83+
+ INIT_WORK(&local->processor, rxrpc_local_processor);
84+
+ INIT_LIST_HEAD(&local->ack_tx_queue);
85+
+ spin_lock_init(&local->ack_tx_lock);
86+
init_rwsem(&local->defrag_sem);
87+
++<<<<<<< HEAD
88+
+ skb_queue_head_init(&local->reject_queue);
89+
+ skb_queue_head_init(&local->event_queue);
90+
++=======
91+
+ init_completion(&local->io_thread_ready);
92+
+ skb_queue_head_init(&local->rx_queue);
93+
+ INIT_LIST_HEAD(&local->call_attend_q);
94+
++>>>>>>> 8fbcc83334a7 (rxrpc: Fix I/O thread startup getting skipped)
95+
local->client_bundles = RB_ROOT;
96+
spin_lock_init(&local->client_bundles_lock);
97+
spin_lock_init(&local->lock);
98+
@@@ -170,8 -183,24 +176,20 @@@ static int rxrpc_open_socket(struct rxr
99+
BUG();
100+
}
101+
102+
++<<<<<<< HEAD
103+
++=======
104+
+ io_thread = kthread_run(rxrpc_io_thread, local,
105+
+ "krxrpcio/%u", ntohs(udp_conf.local_udp_port));
106+
+ if (IS_ERR(io_thread)) {
107+
+ ret = PTR_ERR(io_thread);
108+
+ goto error_sock;
109+
+ }
110+
+
111+
+ wait_for_completion(&local->io_thread_ready);
112+
+ local->io_thread = io_thread;
113+
++>>>>>>> 8fbcc83334a7 (rxrpc: Fix I/O thread startup getting skipped)
114+
_leave(" = 0");
115+
return 0;
116+
-
117+
-error_sock:
118+
- kernel_sock_shutdown(local->socket, SHUT_RDWR);
119+
- local->socket->sk->sk_user_data = NULL;
120+
- sock_release(local->socket);
121+
- local->socket = NULL;
122+
- return ret;
123+
}
124+
125+
/*
126+
* Unmerged path net/rxrpc/io_thread.c
127+
* Unmerged path net/rxrpc/ar-internal.h
128+
* Unmerged path net/rxrpc/io_thread.c
129+
* Unmerged path net/rxrpc/local_object.c

0 commit comments

Comments
 (0)