wireguard: socket: do not hold locks while transmitting packets

Before, we followed this pattern for using the udp_tunnel api:

    rcu_read_lock_bh();
    sock = rcu_dereference(obj->sock);
    ...
    udp_tunnel_xmit_skb(..., sock, ...);
    rcu_read_unlock_bh();

This commit changes that to use a reference counter instead:

    rcu_read_lock_bh();
    sock = rcu_dereference(obj->sock);
    sock_hold(sock);
    rcu_read_unlock_bh();
    ...
    udp_tunnel_xmit_skb(..., sock, ...);
    sock_put(sock);

The advantage of the latter approach is that we now no longer hold any
locks while udp_tunnel_xmit_skb runs, since it could be somewhat slow on
systems with advanced qdisc or netfilter configurations. This should
avoid potential RCU stalls in those situations.

This commit makes sure we're holding neither the rcu read lock nor the
endpoint read lock when udp_tunnel_xmit_skb is called.

Fixes: e7096c131e51 ("net: WireGuard secure network tunnel")
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
1 file changed