diff options
author | Stefano Garzarella <sgarzare@redhat.com> | 2019-10-17 08:44:03 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-10-18 13:19:43 -0400 |
commit | ae6fcfbf5f03de3407b809aaee319330d3dc7f8b (patch) | |
tree | 5fbcf9656666a376a80edc90c21a1de0da79e343 /net | |
parent | ec3359b685db834c249953db6ac5717bf5cde425 (diff) |
vsock/virtio: discard packets if credit is not respected
If the remote peer doesn't respect the credit information
(buf_alloc, fwd_cnt), sending more data than it can send,
we should drop the packets to prevent a malicious peer
from using all of our memory.
This is patch follows the VIRTIO spec: "VIRTIO_VSOCK_OP_RW data
packets MUST only be transmitted when the peer has sufficient
free buffer space for the payload"
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/vmw_vsock/virtio_transport_common.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c index db127a69f5c3..481f7f8a1655 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c | |||
@@ -204,10 +204,14 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk, | |||
204 | return virtio_transport_get_ops()->send_pkt(pkt); | 204 | return virtio_transport_get_ops()->send_pkt(pkt); |
205 | } | 205 | } |
206 | 206 | ||
207 | static void virtio_transport_inc_rx_pkt(struct virtio_vsock_sock *vvs, | 207 | static bool virtio_transport_inc_rx_pkt(struct virtio_vsock_sock *vvs, |
208 | struct virtio_vsock_pkt *pkt) | 208 | struct virtio_vsock_pkt *pkt) |
209 | { | 209 | { |
210 | if (vvs->rx_bytes + pkt->len > vvs->buf_alloc) | ||
211 | return false; | ||
212 | |||
210 | vvs->rx_bytes += pkt->len; | 213 | vvs->rx_bytes += pkt->len; |
214 | return true; | ||
211 | } | 215 | } |
212 | 216 | ||
213 | static void virtio_transport_dec_rx_pkt(struct virtio_vsock_sock *vvs, | 217 | static void virtio_transport_dec_rx_pkt(struct virtio_vsock_sock *vvs, |
@@ -879,14 +883,18 @@ virtio_transport_recv_enqueue(struct vsock_sock *vsk, | |||
879 | struct virtio_vsock_pkt *pkt) | 883 | struct virtio_vsock_pkt *pkt) |
880 | { | 884 | { |
881 | struct virtio_vsock_sock *vvs = vsk->trans; | 885 | struct virtio_vsock_sock *vvs = vsk->trans; |
882 | bool free_pkt = false; | 886 | bool can_enqueue, free_pkt = false; |
883 | 887 | ||
884 | pkt->len = le32_to_cpu(pkt->hdr.len); | 888 | pkt->len = le32_to_cpu(pkt->hdr.len); |
885 | pkt->off = 0; | 889 | pkt->off = 0; |
886 | 890 | ||
887 | spin_lock_bh(&vvs->rx_lock); | 891 | spin_lock_bh(&vvs->rx_lock); |
888 | 892 | ||
889 | virtio_transport_inc_rx_pkt(vvs, pkt); | 893 | can_enqueue = virtio_transport_inc_rx_pkt(vvs, pkt); |
894 | if (!can_enqueue) { | ||
895 | free_pkt = true; | ||
896 | goto out; | ||
897 | } | ||
890 | 898 | ||
891 | /* Try to copy small packets into the buffer of last packet queued, | 899 | /* Try to copy small packets into the buffer of last packet queued, |
892 | * to avoid wasting memory queueing the entire buffer with a small | 900 | * to avoid wasting memory queueing the entire buffer with a small |