]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
vhost/vsock: Avoid allocating arbitrarily-sized SKBs
authorWill Deacon <will@kernel.org>
Thu, 17 Jul 2025 09:01:08 +0000 (10:01 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 28 Aug 2025 14:26:07 +0000 (16:26 +0200)
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>
drivers/vhost/vsock.c

index c00f5821d6ecb5343660a8418f2b336a77951745..1c5096c44fd73989c21f85521ca18d2fdadf4dc6 100644 (file)
@@ -340,6 +340,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)
@@ -363,8 +366,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;
        }