Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a6a0f77f authored by Jason A. Donenfeld's avatar Jason A. Donenfeld Committed by Lee Jones
Browse files

UPSTREAM: wireguard: use synchronize_net rather than synchronize_rcu



Many of the synchronization points are sometimes called under the rtnl
lock, which means we should use synchronize_net rather than
synchronize_rcu. Under the hood, this expands to using the expedited
flavor of function in the event that rtnl is held, in order to not stall
other concurrent changes.

This fixes some very, very long delays when removing multiple peers at
once, which would cause some operations to take several minutes.

Bug: 254441685
Fixes: e7096c131e51 ("net: WireGuard secure network tunnel")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarJason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
(cherry picked from commit 24b70eeeb4f46c09487f8155239ebfb1f875774a)
Signed-off-by: default avatarLee Jones <joneslee@google.com>
Change-Id: I59dc02502d1597c4d05100a874b8a34d61e2eaa5
parent 9d4fd023
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -88,7 +88,7 @@ static void peer_make_dead(struct wg_peer *peer)
	/* Mark as dead, so that we don't allow jumping contexts after. */
	WRITE_ONCE(peer->is_dead, true);

	/* The caller must now synchronize_rcu() for this to take effect. */
	/* The caller must now synchronize_net() for this to take effect. */
}

static void peer_remove_after_dead(struct wg_peer *peer)
@@ -160,7 +160,7 @@ void wg_peer_remove(struct wg_peer *peer)
	lockdep_assert_held(&peer->device->device_update_lock);

	peer_make_dead(peer);
	synchronize_rcu();
	synchronize_net();
	peer_remove_after_dead(peer);
}

@@ -178,7 +178,7 @@ void wg_peer_remove_all(struct wg_device *wg)
		peer_make_dead(peer);
		list_add_tail(&peer->peer_list, &dead_peers);
	}
	synchronize_rcu();
	synchronize_net();
	list_for_each_entry_safe(peer, temp, &dead_peers, peer_list)
		peer_remove_after_dead(peer);
}
+1 −1
Original line number Diff line number Diff line
@@ -430,7 +430,7 @@ void wg_socket_reinit(struct wg_device *wg, struct sock *new4,
	if (new4)
		wg->incoming_port = ntohs(inet_sk(new4)->inet_sport);
	mutex_unlock(&wg->socket_update_lock);
	synchronize_rcu();
	synchronize_net();
	sock_free(old4);
	sock_free(old6);
}