summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2021-08-13 03:00:08 +0200
committerBruno Martins <bgcngm@gmail.com>2023-11-06 09:28:24 +0000
commit0e2c4e57aaa546a2eb234193c41bb87cb01aef35 (patch)
tree8da5f78cb3fc6088a732e8b173ad9d6c13d14d04
parent745e9111c5bb16381cc6fc7ee67400d0390dd93e (diff)
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. Reported-by: Streun Fabio <fstreun@student.ethz.ch> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> Change-Id: I6e0a372a0b26907cc4ac425ecc17bdca8e07a2aa
-rw-r--r--drivers/net/wireguard/receive.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/drivers/net/wireguard/receive.c b/drivers/net/wireguard/receive.c
index d1908b535354..214889edb48e 100644
--- a/drivers/net/wireguard/receive.c
+++ b/drivers/net/wireguard/receive.c
@@ -563,9 +563,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;