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.



Reply via email to