@@ -146,6 +146,13 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
146
146
struct dccp_request_sock * dreq = dccp_rsk (req );
147
147
bool own_req ;
148
148
149
+ /* TCP/DCCP listeners became lockless.
150
+ * DCCP stores complex state in its request_sock, so we need
151
+ * a protection for them, now this code runs without being protected
152
+ * by the parent (listener) lock.
153
+ */
154
+ spin_lock_bh (& dreq -> dreq_lock );
155
+
149
156
/* Check for retransmitted REQUEST */
150
157
if (dccp_hdr (skb )-> dccph_type == DCCP_PKT_REQUEST ) {
151
158
@@ -160,7 +167,7 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
160
167
inet_rtx_syn_ack (sk , req );
161
168
}
162
169
/* Network Duplicate, discard packet */
163
- return NULL ;
170
+ goto out ;
164
171
}
165
172
166
173
DCCP_SKB_CB (skb )-> dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR ;
@@ -186,20 +193,20 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
186
193
187
194
child = inet_csk (sk )-> icsk_af_ops -> syn_recv_sock (sk , skb , req , NULL ,
188
195
req , & own_req );
189
- if (! child )
190
- goto listen_overflow ;
191
-
192
- return inet_csk_complete_hashdance ( sk , child , req , own_req );
196
+ if (child ) {
197
+ child = inet_csk_complete_hashdance ( sk , child , req , own_req ) ;
198
+ goto out ;
199
+ }
193
200
194
- listen_overflow :
195
- dccp_pr_debug ("listen_overflow!\n" );
196
201
DCCP_SKB_CB (skb )-> dccpd_reset_code = DCCP_RESET_CODE_TOO_BUSY ;
197
202
drop :
198
203
if (dccp_hdr (skb )-> dccph_type != DCCP_PKT_RESET )
199
204
req -> rsk_ops -> send_reset (sk , skb );
200
205
201
206
inet_csk_reqsk_queue_drop (sk , req );
202
- return NULL ;
207
+ out :
208
+ spin_unlock_bh (& dreq -> dreq_lock );
209
+ return child ;
203
210
}
204
211
205
212
EXPORT_SYMBOL_GPL (dccp_check_req );
@@ -250,6 +257,7 @@ int dccp_reqsk_init(struct request_sock *req,
250
257
{
251
258
struct dccp_request_sock * dreq = dccp_rsk (req );
252
259
260
+ spin_lock_init (& dreq -> dreq_lock );
253
261
inet_rsk (req )-> ir_rmt_port = dccp_hdr (skb )-> dccph_sport ;
254
262
inet_rsk (req )-> ir_num = ntohs (dccp_hdr (skb )-> dccph_dport );
255
263
inet_rsk (req )-> acked = 0 ;
0 commit comments