Skip to content

Commit 8432b81

Browse files
stefano-garzarelladavem330
authored andcommitted
vsock/virtio: free queued packets when closing socket
As reported by syzbot [1], there is a memory leak while closing the socket. We partially solved this issue with commit ac03046 ("vsock/virtio: free packets during the socket release"), but we forgot to drain the RX queue when the socket is definitely closed by the scheduled work. To avoid future issues, let's use the new virtio_transport_remove_sock() to drain the RX queue before removing the socket from the af_vsock lists calling vsock_remove_sock(). [1] https://syzkaller.appspot.com/bug?extid=24452624fc4c571eedd9 Fixes: ac03046 ("vsock/virtio: free packets during the socket release") Reported-and-tested-by: syzbot+24452624fc4c571eedd9@syzkaller.appspotmail.com Signed-off-by: Stefano Garzarella <sgarzare@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent eeddfd8 commit 8432b81

File tree

1 file changed

+19
-9
lines changed

1 file changed

+19
-9
lines changed

net/vmw_vsock/virtio_transport_common.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,23 @@ static int virtio_transport_reset_no_sock(const struct virtio_transport *t,
733733
return t->send_pkt(reply);
734734
}
735735

736+
/* This function should be called with sk_lock held and SOCK_DONE set */
737+
static void virtio_transport_remove_sock(struct vsock_sock *vsk)
738+
{
739+
struct virtio_vsock_sock *vvs = vsk->trans;
740+
struct virtio_vsock_pkt *pkt, *tmp;
741+
742+
/* We don't need to take rx_lock, as the socket is closing and we are
743+
* removing it.
744+
*/
745+
list_for_each_entry_safe(pkt, tmp, &vvs->rx_queue, list) {
746+
list_del(&pkt->list);
747+
virtio_transport_free_pkt(pkt);
748+
}
749+
750+
vsock_remove_sock(vsk);
751+
}
752+
736753
static void virtio_transport_wait_close(struct sock *sk, long timeout)
737754
{
738755
if (timeout) {
@@ -765,7 +782,7 @@ static void virtio_transport_do_close(struct vsock_sock *vsk,
765782
(!cancel_timeout || cancel_delayed_work(&vsk->close_work))) {
766783
vsk->close_work_scheduled = false;
767784

768-
vsock_remove_sock(vsk);
785+
virtio_transport_remove_sock(vsk);
769786

770787
/* Release refcnt obtained when we scheduled the timeout */
771788
sock_put(sk);
@@ -828,22 +845,15 @@ static bool virtio_transport_close(struct vsock_sock *vsk)
828845

829846
void virtio_transport_release(struct vsock_sock *vsk)
830847
{
831-
struct virtio_vsock_sock *vvs = vsk->trans;
832-
struct virtio_vsock_pkt *pkt, *tmp;
833848
struct sock *sk = &vsk->sk;
834849
bool remove_sock = true;
835850

836851
if (sk->sk_type == SOCK_STREAM)
837852
remove_sock = virtio_transport_close(vsk);
838853

839-
list_for_each_entry_safe(pkt, tmp, &vvs->rx_queue, list) {
840-
list_del(&pkt->list);
841-
virtio_transport_free_pkt(pkt);
842-
}
843-
844854
if (remove_sock) {
845855
sock_set_flag(sk, SOCK_DONE);
846-
vsock_remove_sock(vsk);
856+
virtio_transport_remove_sock(vsk);
847857
}
848858
}
849859
EXPORT_SYMBOL_GPL(virtio_transport_release);

0 commit comments

Comments
 (0)