summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBobby Eshleman <bobby.eshleman@bytedance.com>2023-03-29 16:51:58 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-11-20 11:52:19 +0100
commita6650e78c428841da5d68904475c5d177f3d11ee (patch)
treec6b2608a6833da029b1e535827792aa498433b3b
parentbb1c9a5907d25742c0285e9d7fa518b9f237c944 (diff)
virtio/vsock: fix leaks due to missing skb owner
commit f9d2b1e146e0f82f3d04629afd92698522058361 upstream. This patch sets the skb owner in the recv and send path for virtio. For the send path, this solves the leak caused when virtio_transport_purge_skbs() finds skb->sk is always NULL and therefore never matches it with the current socket. Setting the owner upon allocation fixes this. For the recv path, this ensures correctness of accounting and also correct transfer of ownership in vsock_loopback (when skbs are sent from one socket and received by another). Fixes: 71dc9ec9ac7d ("virtio/vsock: replace virtio_vsock_pkt with sk_buff") Signed-off-by: Bobby Eshleman <bobby.eshleman@bytedance.com> Reported-by: Cong Wang <xiyou.wangcong@gmail.com> Link: https://lore.kernel.org/all/ZCCbATwov4U+GBUv@pop-os.localdomain/ Reviewed-by: Stefano Garzarella <sgarzare@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--net/vmw_vsock/virtio_transport_common.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
index 2b5ca5f18483..0762634dbaee 100644
--- a/net/vmw_vsock/virtio_transport_common.c
+++ b/net/vmw_vsock/virtio_transport_common.c
@@ -94,6 +94,11 @@ virtio_transport_alloc_skb(struct virtio_vsock_pkt_info *info,
info->op,
info->flags);
+ if (info->vsk && !skb_set_owner_sk_safe(skb, sk_vsock(info->vsk))) {
+ WARN_ONCE(1, "failed to allocate skb on vsock socket with sk_refcnt == 0\n");
+ goto out;
+ }
+
return skb;
out:
@@ -1302,6 +1307,11 @@ void virtio_transport_recv_pkt(struct virtio_transport *t,
goto free_pkt;
}
+ if (!skb_set_owner_sk_safe(skb, sk)) {
+ WARN_ONCE(1, "receiving vsock socket has sk_refcnt == 0\n");
+ goto free_pkt;
+ }
+
vsk = vsock_sk(sk);
lock_sock(sk);