On Thu, 2017-03-02 at 05:08 -0800, Eric Dumazet wrote: > Thanks for the report ! > > This patch should solve this precise issue, but we need more work. > > We need to audit all __sk_dst_get() and make sure they are inside an > rcu_read_lock()/rcu_read_unlock() section. > > diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c > index > 22548b5f05cbe5a655e0c53df2d31c5cc2e8a702..517963e1cb6eb9d70fcd71f44262813c3378759f > 100644 > --- a/net/ipv4/tcp_output.c > +++ b/net/ipv4/tcp_output.c > @@ -1459,7 +1459,7 @@ EXPORT_SYMBOL(tcp_sync_mss); > unsigned int tcp_current_mss(struct sock *sk) > { > const struct tcp_sock *tp = tcp_sk(sk); > - const struct dst_entry *dst = __sk_dst_get(sk); > + const struct dst_entry *dst; > u32 mss_now; > unsigned int header_len; > struct tcp_out_options opts; > @@ -1467,11 +1467,14 @@ unsigned int tcp_current_mss(struct sock *sk) > > mss_now = tp->mss_cache; > > + rcu_read_lock(); > + dst = __sk_dst_get(sk); > if (dst) { > u32 mtu = dst_mtu(dst); > if (mtu != inet_csk(sk)->icsk_pmtu_cookie) > mss_now = tcp_sync_mss(sk, mtu); > } > + rcu_read_unlock(); > > header_len = tcp_established_options(sk, NULL, &opts, &md5) + > sizeof(struct tcphdr); >
Normally TCP sockets sk_dst_cache can only be changed if the thread doing the change owns the socket. I have not yet understood which point was breaking the rule yet.