diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2018-02-12 11:57:32 +0100 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2018-02-12 12:04:53 +0100 |
commit | cb86f2cd33a845872198c4bb207bc13e739b2d7e (patch) | |
tree | e5ca71c69d67fae396edfd5e8fd7971dc5e2ce3f | |
parent | d39c586ee03387e9d03f4dff1715fcd309738145 (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.c | 2 |
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); |