• Eric Dumazet's avatar
    ipv6: kill sk_dst_lock · 6bd4f355
    Eric Dumazet authored
    While testing the np->opt RCU conversion, I found that UDP/IPv6 was
    using a mixture of xchg() and sk_dst_lock to protect concurrent changes
    to sk->sk_dst_cache, leading to possible corruptions and crashes.
    
    ip6_sk_dst_lookup_flow() uses sk_dst_check() anyway, so the simplest
    way to fix the mess is to remove sk_dst_lock completely, as we did for
    IPv4.
    
    __ip6_dst_store() and ip6_dst_store() share same implementation.
    
    sk_setup_caps() being called with socket lock being held or not,
    we have to use sk_dst_set() instead of __sk_dst_set()
    
    Note that I had to move the "np->dst_cookie = rt6_get_cookie(rt);"
    in ip6_dst_store() before the sk_setup_caps(sk, dst) call.
    
    This is because ip6_dst_store() can be called from process context,
    without any lock held.
    
    As soon as the dst is installed in sk->sk_dst_cache, dst can be freed
    from another cpu doing a concurrent ip6_dst_store()
    
    Doing the dst dereference before doing the install is needed to make
    sure no use after free would trigger.
    Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
    Reported-by: default avatarDmitry Vyukov <dvyukov@google.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    6bd4f355
inet6_connection_sock.c 5.29 KB