b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| 2 | From: "Jason A. Donenfeld" <Jason@zx2c4.com> |
| 3 | Date: Fri, 4 Jun 2021 17:17:33 +0200 |
| 4 | Subject: [PATCH] wireguard: use synchronize_net rather than synchronize_rcu |
| 5 | |
| 6 | commit 24b70eeeb4f46c09487f8155239ebfb1f875774a upstream. |
| 7 | |
| 8 | Many of the synchronization points are sometimes called under the rtnl |
| 9 | lock, which means we should use synchronize_net rather than |
| 10 | synchronize_rcu. Under the hood, this expands to using the expedited |
| 11 | flavor of function in the event that rtnl is held, in order to not stall |
| 12 | other concurrent changes. |
| 13 | |
| 14 | This fixes some very, very long delays when removing multiple peers at |
| 15 | once, which would cause some operations to take several minutes. |
| 16 | |
| 17 | Fixes: e7096c131e51 ("net: WireGuard secure network tunnel") |
| 18 | Cc: stable@vger.kernel.org |
| 19 | Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> |
| 20 | Signed-off-by: David S. Miller <davem@davemloft.net> |
| 21 | Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> |
| 22 | --- |
| 23 | drivers/net/wireguard/peer.c | 6 +++--- |
| 24 | drivers/net/wireguard/socket.c | 2 +- |
| 25 | 2 files changed, 4 insertions(+), 4 deletions(-) |
| 26 | |
| 27 | --- a/drivers/net/wireguard/peer.c |
| 28 | +++ b/drivers/net/wireguard/peer.c |
| 29 | @@ -88,7 +88,7 @@ static void peer_make_dead(struct wg_pee |
| 30 | /* Mark as dead, so that we don't allow jumping contexts after. */ |
| 31 | WRITE_ONCE(peer->is_dead, true); |
| 32 | |
| 33 | - /* The caller must now synchronize_rcu() for this to take effect. */ |
| 34 | + /* The caller must now synchronize_net() for this to take effect. */ |
| 35 | } |
| 36 | |
| 37 | static void peer_remove_after_dead(struct wg_peer *peer) |
| 38 | @@ -160,7 +160,7 @@ void wg_peer_remove(struct wg_peer *peer |
| 39 | lockdep_assert_held(&peer->device->device_update_lock); |
| 40 | |
| 41 | peer_make_dead(peer); |
| 42 | - synchronize_rcu(); |
| 43 | + synchronize_net(); |
| 44 | peer_remove_after_dead(peer); |
| 45 | } |
| 46 | |
| 47 | @@ -178,7 +178,7 @@ void wg_peer_remove_all(struct wg_device |
| 48 | peer_make_dead(peer); |
| 49 | list_add_tail(&peer->peer_list, &dead_peers); |
| 50 | } |
| 51 | - synchronize_rcu(); |
| 52 | + synchronize_net(); |
| 53 | list_for_each_entry_safe(peer, temp, &dead_peers, peer_list) |
| 54 | peer_remove_after_dead(peer); |
| 55 | } |
| 56 | --- a/drivers/net/wireguard/socket.c |
| 57 | +++ b/drivers/net/wireguard/socket.c |
| 58 | @@ -430,7 +430,7 @@ void wg_socket_reinit(struct wg_device * |
| 59 | if (new4) |
| 60 | wg->incoming_port = ntohs(inet_sk(new4)->inet_sport); |
| 61 | mutex_unlock(&wg->socket_update_lock); |
| 62 | - synchronize_rcu(); |
| 63 | + synchronize_net(); |
| 64 | sock_free(old4); |
| 65 | sock_free(old6); |
| 66 | } |