Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4bdc3d66 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

tcp/dccp: fix behavior of stale SYN_RECV request sockets



When a TCP/DCCP listener is closed, its pending SYN_RECV request sockets
become stale, meaning 3WHS can not complete.

But current behavior is wrong :
incoming packets finding such stale sockets are dropped.

We need instead to cleanup the request socket and perform another
lookup :
- Incoming ACK will give a RST answer,
- SYN rtx might find another listener if available.
- We expedite cleanup of request sockets and old listener socket.

Fixes: 079096f1 ("tcp/dccp: install syn_recv requests into ehash table")
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bbb300eb
Loading
Loading
Loading
Loading
+7 −8
Original line number Diff line number Diff line
@@ -799,15 +799,10 @@ static int dccp_v4_rcv(struct sk_buff *skb)
				  DCCP_SKB_CB(skb)->dccpd_ack_seq);
	}

	/* Step 2:
	 *	Look up flow ID in table and get corresponding socket */
lookup:
	sk = __inet_lookup_skb(&dccp_hashinfo, skb,
			       dh->dccph_sport, dh->dccph_dport);
	/*
	 * Step 2:
	 *	If no socket ...
	 */
	if (sk == NULL) {
	if (!sk) {
		dccp_pr_debug("failed to look up flow ID in table and "
			      "get corresponding socket\n");
		goto no_dccp_socket;
@@ -830,8 +825,12 @@ static int dccp_v4_rcv(struct sk_buff *skb)
		struct sock *nsk = NULL;

		sk = req->rsk_listener;
		if (sk->sk_state == DCCP_LISTEN)
		if (likely(sk->sk_state == DCCP_LISTEN)) {
			nsk = dccp_check_req(sk, skb, req);
		} else {
			inet_csk_reqsk_queue_drop(sk, req);
			goto lookup;
		}
		if (!nsk) {
			reqsk_put(req);
			goto discard_it;
+7 −8
Original line number Diff line number Diff line
@@ -656,16 +656,11 @@ static int dccp_v6_rcv(struct sk_buff *skb)
	else
		DCCP_SKB_CB(skb)->dccpd_ack_seq = dccp_hdr_ack_seq(skb);

	/* Step 2:
	 *	Look up flow ID in table and get corresponding socket */
lookup:
	sk = __inet6_lookup_skb(&dccp_hashinfo, skb,
			        dh->dccph_sport, dh->dccph_dport,
				inet6_iif(skb));
	/*
	 * Step 2:
	 *	If no socket ...
	 */
	if (sk == NULL) {
	if (!sk) {
		dccp_pr_debug("failed to look up flow ID in table and "
			      "get corresponding socket\n");
		goto no_dccp_socket;
@@ -688,8 +683,12 @@ static int dccp_v6_rcv(struct sk_buff *skb)
		struct sock *nsk = NULL;

		sk = req->rsk_listener;
		if (sk->sk_state == DCCP_LISTEN)
		if (likely(sk->sk_state == DCCP_LISTEN)) {
			nsk = dccp_check_req(sk, skb, req);
		} else {
			inet_csk_reqsk_queue_drop(sk, req);
			goto lookup;
		}
		if (!nsk) {
			reqsk_put(req);
			goto discard_it;
+6 −1
Original line number Diff line number Diff line
@@ -1572,6 +1572,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
	TCP_SKB_CB(skb)->ip_dsfield = ipv4_get_dsfield(iph);
	TCP_SKB_CB(skb)->sacked	 = 0;

lookup:
	sk = __inet_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest);
	if (!sk)
		goto no_tcp_socket;
@@ -1587,8 +1588,12 @@ int tcp_v4_rcv(struct sk_buff *skb)
		sk = req->rsk_listener;
		if (tcp_v4_inbound_md5_hash(sk, skb))
			goto discard_and_relse;
		if (sk->sk_state == TCP_LISTEN)
		if (likely(sk->sk_state == TCP_LISTEN)) {
			nsk = tcp_check_req(sk, skb, req, false);
		} else {
			inet_csk_reqsk_queue_drop(sk, req);
			goto lookup;
		}
		if (!nsk) {
			reqsk_put(req);
			goto discard_it;
+6 −1
Original line number Diff line number Diff line
@@ -1363,6 +1363,7 @@ static int tcp_v6_rcv(struct sk_buff *skb)
	th = tcp_hdr(skb);
	hdr = ipv6_hdr(skb);

lookup:
	sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest,
				inet6_iif(skb));
	if (!sk)
@@ -1382,8 +1383,12 @@ static int tcp_v6_rcv(struct sk_buff *skb)
			reqsk_put(req);
			goto discard_it;
		}
		if (sk->sk_state == TCP_LISTEN)
		if (likely(sk->sk_state == TCP_LISTEN)) {
			nsk = tcp_check_req(sk, skb, req, false);
		} else {
			inet_csk_reqsk_queue_drop(sk, req);
			goto lookup;
		}
		if (!nsk) {
			reqsk_put(req);
			goto discard_it;