@@ -146,6 +146,13 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
146146 struct dccp_request_sock * dreq = dccp_rsk (req );
147147 bool own_req ;
148148
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+
149156 /* Check for retransmitted REQUEST */
150157 if (dccp_hdr (skb )-> dccph_type == DCCP_PKT_REQUEST ) {
151158
@@ -160,7 +167,7 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
160167 inet_rtx_syn_ack (sk , req );
161168 }
162169 /* Network Duplicate, discard packet */
163- return NULL ;
170+ goto out ;
164171 }
165172
166173 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,
186193
187194 child = inet_csk (sk )-> icsk_af_ops -> syn_recv_sock (sk , skb , req , NULL ,
188195 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+ }
193200
194- listen_overflow :
195- dccp_pr_debug ("listen_overflow!\n" );
196201 DCCP_SKB_CB (skb )-> dccpd_reset_code = DCCP_RESET_CODE_TOO_BUSY ;
197202drop :
198203 if (dccp_hdr (skb )-> dccph_type != DCCP_PKT_RESET )
199204 req -> rsk_ops -> send_reset (sk , skb );
200205
201206 inet_csk_reqsk_queue_drop (sk , req );
202- return NULL ;
207+ out :
208+ spin_unlock_bh (& dreq -> dreq_lock );
209+ return child ;
203210}
204211
205212EXPORT_SYMBOL_GPL (dccp_check_req );
@@ -250,6 +257,7 @@ int dccp_reqsk_init(struct request_sock *req,
250257{
251258 struct dccp_request_sock * dreq = dccp_rsk (req );
252259
260+ spin_lock_init (& dreq -> dreq_lock );
253261 inet_rsk (req )-> ir_rmt_port = dccp_hdr (skb )-> dccph_sport ;
254262 inet_rsk (req )-> ir_num = ntohs (dccp_hdr (skb )-> dccph_dport );
255263 inet_rsk (req )-> acked = 0 ;
0 commit comments