58 lines
2.0 KiB
Diff
58 lines
2.0 KiB
Diff
From cfb5ffceff501d3ffe6529706d65a35e6068b638 Mon Sep 17 00:00:00 2001
|
|
From: Will Deacon <will@kernel.org>
|
|
Date: Thu, 17 Jul 2025 10:01:09 +0100
|
|
Subject: vsock/virtio: Validate length in packet header before skb_put()
|
|
|
|
When receiving a vsock packet in the guest, only the virtqueue buffer
|
|
size is validated prior to virtio_vsock_skb_rx_put(). Unfortunately,
|
|
virtio_vsock_skb_rx_put() uses the length from the packet header as the
|
|
length argument to skb_put(), potentially resulting in SKB overflow if
|
|
the host has gone wonky.
|
|
|
|
Validate the length as advertised by the packet header before calling
|
|
virtio_vsock_skb_rx_put().
|
|
|
|
Cc: <stable@vger.kernel.org>
|
|
Fixes: 71dc9ec9ac7d ("virtio/vsock: replace virtio_vsock_pkt with sk_buff")
|
|
Signed-off-by: Will Deacon <will@kernel.org>
|
|
Message-Id: <20250717090116.11987-3-will@kernel.org>
|
|
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
|
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
|
|
---
|
|
net/vmw_vsock/virtio_transport.c | 12 ++++++++++--
|
|
1 file changed, 10 insertions(+), 2 deletions(-)
|
|
|
|
--- a/net/vmw_vsock/virtio_transport.c
|
|
+++ b/net/vmw_vsock/virtio_transport.c
|
|
@@ -624,8 +624,9 @@ static void virtio_transport_rx_work(str
|
|
do {
|
|
virtqueue_disable_cb(vq);
|
|
for (;;) {
|
|
+ unsigned int len, payload_len;
|
|
+ struct virtio_vsock_hdr *hdr;
|
|
struct sk_buff *skb;
|
|
- unsigned int len;
|
|
|
|
if (!virtio_transport_more_replies(vsock)) {
|
|
/* Stop rx until the device processes already
|
|
@@ -642,11 +643,18 @@ static void virtio_transport_rx_work(str
|
|
vsock->rx_buf_nr--;
|
|
|
|
/* Drop short/long packets */
|
|
- if (unlikely(len < sizeof(struct virtio_vsock_hdr) ||
|
|
+ if (unlikely(len < sizeof(*hdr) ||
|
|
len > virtio_vsock_skb_len(skb))) {
|
|
kfree_skb(skb);
|
|
continue;
|
|
}
|
|
+
|
|
+ hdr = virtio_vsock_hdr(skb);
|
|
+ payload_len = le32_to_cpu(hdr->len);
|
|
+ if (unlikely(payload_len > len - sizeof(*hdr))) {
|
|
+ kfree_skb(skb);
|
|
+ continue;
|
|
+ }
|
|
|
|
virtio_vsock_skb_rx_put(skb);
|
|
virtio_transport_deliver_tap_pkt(skb);
|