mirror of
https://github.com/torvalds/linux.git
synced 2026-06-02 11:33:28 +02:00
vsock/virtio: reset connection on receiving queue overflow
When there is no more space to queue an incoming packet, the packet is silently dropped. This causes data loss without any notification to either peer, since there is no retransmission. Under normal circumstances, this should never happen. However, it could happen if the other peer doesn't respect the credit, or if the skb overhead, which we recently began to take into account with commit059b7dbd20("vsock/virtio: fix potential unbounded skb queue"), is too high. Fix this by resetting the connection and setting the local socket error to ENOBUFS when virtio_transport_recv_enqueue() can no longer queue a packet, so both peers are explicitly notified of the failure rather than silently losing data. Fixes:ae6fcfbf5f("vsock/virtio: discard packets if credit is not respected") Cc: stable@vger.kernel.org Signed-off-by: Stefano Garzarella <sgarzare@redhat.com> Link: https://patch.msgid.link/20260518090656.134588-2-sgarzare@redhat.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
0377bd2722
commit
a4f0b00178
|
|
@ -1335,7 +1335,7 @@ virtio_transport_recv_connecting(struct sock *sk,
|
|||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
static bool
|
||||
virtio_transport_recv_enqueue(struct vsock_sock *vsk,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
|
|
@ -1350,10 +1350,8 @@ virtio_transport_recv_enqueue(struct vsock_sock *vsk,
|
|||
spin_lock_bh(&vvs->rx_lock);
|
||||
|
||||
can_enqueue = virtio_transport_inc_rx_pkt(vvs, len);
|
||||
if (!can_enqueue) {
|
||||
free_pkt = true;
|
||||
if (!can_enqueue)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (le32_to_cpu(hdr->flags) & VIRTIO_VSOCK_SEQ_EOM)
|
||||
vvs->msg_count++;
|
||||
|
|
@ -1393,6 +1391,8 @@ virtio_transport_recv_enqueue(struct vsock_sock *vsk,
|
|||
spin_unlock_bh(&vvs->rx_lock);
|
||||
if (free_pkt)
|
||||
kfree_skb(skb);
|
||||
|
||||
return can_enqueue;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -1405,7 +1405,17 @@ virtio_transport_recv_connected(struct sock *sk,
|
|||
|
||||
switch (le16_to_cpu(hdr->op)) {
|
||||
case VIRTIO_VSOCK_OP_RW:
|
||||
virtio_transport_recv_enqueue(vsk, skb);
|
||||
if (!virtio_transport_recv_enqueue(vsk, skb)) {
|
||||
/* There is no more space to queue the packet, so let's
|
||||
* close the connection; otherwise, we'll lose data.
|
||||
*/
|
||||
(void)virtio_transport_reset(vsk, skb);
|
||||
virtio_transport_do_close(vsk, true);
|
||||
sk->sk_err = ENOBUFS;
|
||||
sk_error_report(sk);
|
||||
vsock_remove_sock(vsk);
|
||||
break;
|
||||
}
|
||||
vsock_data_ready(sk);
|
||||
return err;
|
||||
case VIRTIO_VSOCK_OP_CREDIT_REQUEST:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user