Commit 0d4f0608619de59fd8169dd8e72aadc28d80e715
Committed by
David S. Miller
1 parent
b009aac12c
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
tcp: dont handle MTU reduction on LISTEN socket
When an ICMP ICMP_FRAG_NEEDED (or ICMPV6_PKT_TOOBIG) message finds a LISTEN socket, and this socket is currently owned by the user, we set TCP_MTU_REDUCED_DEFERRED flag in listener tsq_flags. This is bad because if we clone the parent before it had a chance to clear the flag, the child inherits the tsq_flags value, and next tcp_release_cb() on the child will decrement sk_refcnt. Result is that we might free a live TCP socket, as reported by Dormando. IPv4: Attempt to release TCP socket in state 1 Fix this issue by testing sk_state against TCP_LISTEN early, so that we set TCP_MTU_REDUCED_DEFERRED on appropriate sockets (not a LISTEN one) This bug was introduced in commit 563d34d05786 (tcp: dont drop MTU reduction indications) Reported-by: dormando <dormando@rydia.net> Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 2 changed files with 14 additions and 7 deletions Side-by-side Diff
net/ipv4/tcp_ipv4.c
... | ... | @@ -274,13 +274,6 @@ |
274 | 274 | struct inet_sock *inet = inet_sk(sk); |
275 | 275 | u32 mtu = tcp_sk(sk)->mtu_info; |
276 | 276 | |
277 | - /* We are not interested in TCP_LISTEN and open_requests (SYN-ACKs | |
278 | - * send out by Linux are always <576bytes so they should go through | |
279 | - * unfragmented). | |
280 | - */ | |
281 | - if (sk->sk_state == TCP_LISTEN) | |
282 | - return; | |
283 | - | |
284 | 277 | dst = inet_csk_update_pmtu(sk, mtu); |
285 | 278 | if (!dst) |
286 | 279 | return; |
... | ... | @@ -408,6 +401,13 @@ |
408 | 401 | goto out; |
409 | 402 | |
410 | 403 | if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */ |
404 | + /* We are not interested in TCP_LISTEN and open_requests | |
405 | + * (SYN-ACKs send out by Linux are always <576bytes so | |
406 | + * they should go through unfragmented). | |
407 | + */ | |
408 | + if (sk->sk_state == TCP_LISTEN) | |
409 | + goto out; | |
410 | + | |
411 | 411 | tp->mtu_info = info; |
412 | 412 | if (!sock_owned_by_user(sk)) { |
413 | 413 | tcp_v4_mtu_reduced(sk); |
net/ipv6/tcp_ipv6.c
... | ... | @@ -389,6 +389,13 @@ |
389 | 389 | } |
390 | 390 | |
391 | 391 | if (type == ICMPV6_PKT_TOOBIG) { |
392 | + /* We are not interested in TCP_LISTEN and open_requests | |
393 | + * (SYN-ACKs send out by Linux are always <576bytes so | |
394 | + * they should go through unfragmented). | |
395 | + */ | |
396 | + if (sk->sk_state == TCP_LISTEN) | |
397 | + goto out; | |
398 | + | |
392 | 399 | tp->mtu_info = ntohl(info); |
393 | 400 | if (!sock_owned_by_user(sk)) |
394 | 401 | tcp_v6_mtu_reduced(sk); |