Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tcp: fix tcp_release_cb() to dispatch via address family for mtu_reduced()

Make sure we use the correct address-family-specific function for
handling MTU reductions from within tcp_release_cb().

Previously AF_INET6 sockets were incorrectly always using the IPv6
code path when sometimes they were handling IPv4 traffic and thus had
an IPv4 dst.

Signed-off-by: Neal Cardwell <ncardwell@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Diagnosed-by: Willem de Bruijn <willemb@google.com>
Fixes: 563d34d057862 ("tcp: dont drop MTU reduction indications")
Reviewed-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Neal Cardwell and committed by
David S. Miller
4fab9071 bc8fc7b8

+8 -5
+1
include/net/inet_connection_sock.h
··· 62 62 void (*addr2sockaddr)(struct sock *sk, struct sockaddr *); 63 63 int (*bind_conflict)(const struct sock *sk, 64 64 const struct inet_bind_bucket *tb, bool relax); 65 + void (*mtu_reduced)(struct sock *sk); 65 66 }; 66 67 67 68 /** inet_connection_sock - INET connection oriented sock
-1
include/net/sock.h
··· 987 987 struct sk_buff *skb); 988 988 989 989 void (*release_cb)(struct sock *sk); 990 - void (*mtu_reduced)(struct sock *sk); 991 990 992 991 /* Keeping track of sk's, looking them up, and port selection methods. */ 993 992 void (*hash)(struct sock *sk);
+1
include/net/tcp.h
··· 448 448 */ 449 449 450 450 void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb); 451 + void tcp_v4_mtu_reduced(struct sock *sk); 451 452 int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb); 452 453 struct sock *tcp_create_openreq_child(struct sock *sk, 453 454 struct request_sock *req,
+3 -2
net/ipv4/tcp_ipv4.c
··· 271 271 * It can be called through tcp_release_cb() if socket was owned by user 272 272 * at the time tcp_v4_err() was called to handle ICMP message. 273 273 */ 274 - static void tcp_v4_mtu_reduced(struct sock *sk) 274 + void tcp_v4_mtu_reduced(struct sock *sk) 275 275 { 276 276 struct dst_entry *dst; 277 277 struct inet_sock *inet = inet_sk(sk); ··· 302 302 tcp_simple_retransmit(sk); 303 303 } /* else let the usual retransmit timer handle it */ 304 304 } 305 + EXPORT_SYMBOL(tcp_v4_mtu_reduced); 305 306 306 307 static void do_redirect(struct sk_buff *skb, struct sock *sk) 307 308 { ··· 1788 1787 .compat_setsockopt = compat_ip_setsockopt, 1789 1788 .compat_getsockopt = compat_ip_getsockopt, 1790 1789 #endif 1790 + .mtu_reduced = tcp_v4_mtu_reduced, 1791 1791 }; 1792 1792 EXPORT_SYMBOL(ipv4_specific); 1793 1793 ··· 2408 2406 .sendpage = tcp_sendpage, 2409 2407 .backlog_rcv = tcp_v4_do_rcv, 2410 2408 .release_cb = tcp_release_cb, 2411 - .mtu_reduced = tcp_v4_mtu_reduced, 2412 2409 .hash = inet_hash, 2413 2410 .unhash = inet_unhash, 2414 2411 .get_port = inet_csk_get_port,
+1 -1
net/ipv4/tcp_output.c
··· 800 800 __sock_put(sk); 801 801 } 802 802 if (flags & (1UL << TCP_MTU_REDUCED_DEFERRED)) { 803 - sk->sk_prot->mtu_reduced(sk); 803 + inet_csk(sk)->icsk_af_ops->mtu_reduced(sk); 804 804 __sock_put(sk); 805 805 } 806 806 }
+2 -1
net/ipv6/tcp_ipv6.c
··· 1595 1595 .compat_setsockopt = compat_ipv6_setsockopt, 1596 1596 .compat_getsockopt = compat_ipv6_getsockopt, 1597 1597 #endif 1598 + .mtu_reduced = tcp_v6_mtu_reduced, 1598 1599 }; 1599 1600 1600 1601 #ifdef CONFIG_TCP_MD5SIG ··· 1626 1625 .compat_setsockopt = compat_ipv6_setsockopt, 1627 1626 .compat_getsockopt = compat_ipv6_getsockopt, 1628 1627 #endif 1628 + .mtu_reduced = tcp_v4_mtu_reduced, 1629 1629 }; 1630 1630 1631 1631 #ifdef CONFIG_TCP_MD5SIG ··· 1866 1864 .sendpage = tcp_sendpage, 1867 1865 .backlog_rcv = tcp_v6_do_rcv, 1868 1866 .release_cb = tcp_release_cb, 1869 - .mtu_reduced = tcp_v6_mtu_reduced, 1870 1867 .hash = tcp_v6_hash, 1871 1868 .unhash = inet_unhash, 1872 1869 .get_port = inet_csk_get_port,