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

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

UPSTREAM: wireguard: receive: drop handshakes if queue lock is contended



If we're being delivered packets from multiple CPUs so quickly that the
ring lock is contended for CPU tries, then it's safe to assume that the
queue is near capacity anyway, so just drop the packet rather than
spinning. This helps deal with multicore DoS that can interfere with
data path performance. It _still_ does not completely fix the issue, but
it again chips away at it.

Bug: 254441685
Reported-by: default avatarStreun Fabio <fstreun@student.ethz.ch>
Fixes: e7096c131e51 ("net: WireGuard secure network tunnel")
Signed-off-by: default avatarJason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
(cherry picked from commit fb32f4f606c17b869805d7cede8b03d78339b50a)
Signed-off-by: default avatarLee Jones <joneslee@google.com>
Change-Id: Ifa280bd0891b5987c672b24d9800afa44e7dc12c
parent 8dda6125
Loading
Loading
Loading
Loading
+13 −3
Original line number Diff line number Diff line
@@ -554,9 +554,19 @@ void wg_packet_receive(struct wg_device *wg, struct sk_buff *skb)
	case cpu_to_le32(MESSAGE_HANDSHAKE_INITIATION):
	case cpu_to_le32(MESSAGE_HANDSHAKE_RESPONSE):
	case cpu_to_le32(MESSAGE_HANDSHAKE_COOKIE): {
		int cpu;
		if (unlikely(!rng_is_initialized() ||
			     ptr_ring_produce_bh(&wg->handshake_queue.ring, skb))) {
		int cpu, ret = -EBUSY;

		if (unlikely(!rng_is_initialized()))
			goto drop;
		if (atomic_read(&wg->handshake_queue_len) > MAX_QUEUED_INCOMING_HANDSHAKES / 2) {
			if (spin_trylock_bh(&wg->handshake_queue.ring.producer_lock)) {
				ret = __ptr_ring_produce(&wg->handshake_queue.ring, skb);
				spin_unlock_bh(&wg->handshake_queue.ring.producer_lock);
			}
		} else
			ret = ptr_ring_produce_bh(&wg->handshake_queue.ring, skb);
		if (ret) {
	drop:
			net_dbg_skb_ratelimited("%s: Dropping handshake packet from %pISpfsc\n",
						wg->dev->name, skb);
			goto err;