summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2018-02-12 11:57:32 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2018-02-12 12:04:53 +0100
commitcb86f2cd33a845872198c4bb207bc13e739b2d7e (patch)
treee5ca71c69d67fae396edfd5e8fd7971dc5e2ce3f
parentd39c586ee03387e9d03f4dff1715fcd309738145 (diff)
socket: free skb if there isn't an endpoint
Because the packet transmission interface in Linux, in general, has the characteristic of "consuming" skbs, our own socket_send family too must always consume skbs. This means that when a caller passes an skb to a socket_send function, he looses ownership and expects for the skb to be freed by the socket_send function, not by himself. Therefore, it's important that we actually carry out this contract under all circumstances, even when there's no endpoint available. This condition could be hit by setting up a peer with a persistent keepalive but no endpoint, or by removing an endpoint once packets were queued up to be sent already. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--src/socket.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/src/socket.c b/src/socket.c
index 8eefa87..6c81cc6 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -163,6 +163,8 @@ int socket_send_skb_to_peer(struct wireguard_peer *peer, struct sk_buff *skb, u8
ret = send4(peer->device, skb, &peer->endpoint, ds, &peer->endpoint_cache);
else if (peer->endpoint.addr.sa_family == AF_INET6)
ret = send6(peer->device, skb, &peer->endpoint, ds, &peer->endpoint_cache);
+ else
+ dev_kfree_skb(skb);
if (likely(!ret))
peer->tx_bytes += skb_len;
read_unlock_bh(&peer->endpoint_lock);