summaryrefslogtreecommitdiff
path: root/drivers/vhost
diff options
context:
space:
mode:
authorWill Deacon <will@kernel.org>2025-07-17 10:01:08 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-08-28 16:30:59 +0200
commit21d9382c44a46c8400bb1da2d8a2fc56bc00d3c5 (patch)
tree52f9dc532f2bb161a5d1ca17156cb6976cf91cc3 /drivers/vhost
parentfaf332a10372390ce65d0b803888f4b25a388335 (diff)
downloadlinux-21d9382c44a46c8400bb1da2d8a2fc56bc00d3c5.tar.gz
linux-21d9382c44a46c8400bb1da2d8a2fc56bc00d3c5.tar.bz2
linux-21d9382c44a46c8400bb1da2d8a2fc56bc00d3c5.zip
vhost/vsock: Avoid allocating arbitrarily-sized SKBs
commit 10a886aaed293c4db3417951f396827216299e3d upstream. vhost_vsock_alloc_skb() returns NULL for packets advertising a length larger than VIRTIO_VSOCK_MAX_PKT_BUF_SIZE in the packet header. However, this is only checked once the SKB has been allocated and, if the length in the packet header is zero, the SKB may not be freed immediately. Hoist the size check before the SKB allocation so that an iovec larger than VIRTIO_VSOCK_MAX_PKT_BUF_SIZE + the header size is rejected outright. The subsequent check on the length field in the header can then simply check that the allocated SKB is indeed large enough to hold the packet. Cc: <stable@vger.kernel.org> Fixes: 71dc9ec9ac7d ("virtio/vsock: replace virtio_vsock_pkt with sk_buff") Reviewed-by: Stefano Garzarella <sgarzare@redhat.com> Signed-off-by: Will Deacon <will@kernel.org> Message-Id: <20250717090116.11987-2-will@kernel.org> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/vhost')
-rw-r--r--drivers/vhost/vsock.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
index 802153e23073..66a0f060770e 100644
--- a/drivers/vhost/vsock.c
+++ b/drivers/vhost/vsock.c
@@ -344,6 +344,9 @@ vhost_vsock_alloc_skb(struct vhost_virtqueue *vq,
len = iov_length(vq->iov, out);
+ if (len > VIRTIO_VSOCK_MAX_PKT_BUF_SIZE + VIRTIO_VSOCK_SKB_HEADROOM)
+ return NULL;
+
/* len contains both payload and hdr */
skb = virtio_vsock_alloc_skb(len, GFP_KERNEL);
if (!skb)
@@ -367,8 +370,7 @@ vhost_vsock_alloc_skb(struct vhost_virtqueue *vq,
return skb;
/* The pkt is too big or the length in the header is invalid */
- if (payload_len > VIRTIO_VSOCK_MAX_PKT_BUF_SIZE ||
- payload_len + sizeof(*hdr) > len) {
+ if (payload_len + sizeof(*hdr) > len) {
kfree_skb(skb);
return NULL;
}