* [PATCH v3 1/9] vhost/vsock: Avoid allocating arbitrarily-sized SKBs
[not found] <20250714152103.6949-1-will@kernel.org>
@ 2025-07-14 15:20 ` Will Deacon
2025-07-15 9:47 ` Stefano Garzarella
2025-07-14 15:20 ` [PATCH v3 2/9] vsock/virtio: Validate length in packet header before skb_put() Will Deacon
1 sibling, 1 reply; 4+ messages in thread
From: Will Deacon @ 2025-07-14 15:20 UTC (permalink / raw)
To: linux-kernel
Cc: Will Deacon, Keir Fraser, Steven Moreland, Frederick Mayle,
Stefan Hajnoczi, Stefano Garzarella, Michael S. Tsirkin,
Jason Wang, Eugenio Pérez, netdev, virtualization, stable
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")
Signed-off-by: Will Deacon <will@kernel.org>
---
drivers/vhost/vsock.c | 6 ++++--
1 file 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;
}
--
2.50.0.727.gbf7dc18ff4-goog
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v3 2/9] vsock/virtio: Validate length in packet header before skb_put()
[not found] <20250714152103.6949-1-will@kernel.org>
2025-07-14 15:20 ` [PATCH v3 1/9] vhost/vsock: Avoid allocating arbitrarily-sized SKBs Will Deacon
@ 2025-07-14 15:20 ` Will Deacon
2025-07-15 9:53 ` Stefano Garzarella
1 sibling, 1 reply; 4+ messages in thread
From: Will Deacon @ 2025-07-14 15:20 UTC (permalink / raw)
To: linux-kernel
Cc: Will Deacon, Keir Fraser, Steven Moreland, Frederick Mayle,
Stefan Hajnoczi, Stefano Garzarella, Michael S. Tsirkin,
Jason Wang, Eugenio Pérez, netdev, virtualization, stable
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>
---
net/vmw_vsock/virtio_transport.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c
index f0e48e6911fc..bd2c6aaa1a93 100644
--- a/net/vmw_vsock/virtio_transport.c
+++ b/net/vmw_vsock/virtio_transport.c
@@ -624,8 +624,9 @@ static void virtio_transport_rx_work(struct work_struct *work)
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,12 +643,19 @@ static void virtio_transport_rx_work(struct work_struct *work)
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 (payload_len > len - sizeof(*hdr)) {
+ kfree_skb(skb);
+ continue;
+ }
+
virtio_vsock_skb_rx_put(skb);
virtio_transport_deliver_tap_pkt(skb);
virtio_transport_recv_pkt(&virtio_transport, skb);
--
2.50.0.727.gbf7dc18ff4-goog
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v3 1/9] vhost/vsock: Avoid allocating arbitrarily-sized SKBs
2025-07-14 15:20 ` [PATCH v3 1/9] vhost/vsock: Avoid allocating arbitrarily-sized SKBs Will Deacon
@ 2025-07-15 9:47 ` Stefano Garzarella
0 siblings, 0 replies; 4+ messages in thread
From: Stefano Garzarella @ 2025-07-15 9:47 UTC (permalink / raw)
To: Will Deacon
Cc: linux-kernel, Keir Fraser, Steven Moreland, Frederick Mayle,
Stefan Hajnoczi, Michael S. Tsirkin, Jason Wang,
Eugenio Pérez, netdev, virtualization, stable
On Mon, Jul 14, 2025 at 04:20:55PM +0100, Will Deacon wrote:
>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")
>Signed-off-by: Will Deacon <will@kernel.org>
>---
> drivers/vhost/vsock.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
>
>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;
> }
>--
>2.50.0.727.gbf7dc18ff4-goog
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v3 2/9] vsock/virtio: Validate length in packet header before skb_put()
2025-07-14 15:20 ` [PATCH v3 2/9] vsock/virtio: Validate length in packet header before skb_put() Will Deacon
@ 2025-07-15 9:53 ` Stefano Garzarella
0 siblings, 0 replies; 4+ messages in thread
From: Stefano Garzarella @ 2025-07-15 9:53 UTC (permalink / raw)
To: Will Deacon
Cc: linux-kernel, Keir Fraser, Steven Moreland, Frederick Mayle,
Stefan Hajnoczi, Michael S. Tsirkin, Jason Wang,
Eugenio Pérez, netdev, virtualization, stable
On Mon, Jul 14, 2025 at 04:20:56PM +0100, Will Deacon wrote:
>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>
>---
> net/vmw_vsock/virtio_transport.c | 12 ++++++++++--
> 1 file changed, 10 insertions(+), 2 deletions(-)
>
>diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c
>index f0e48e6911fc..bd2c6aaa1a93 100644
>--- a/net/vmw_vsock/virtio_transport.c
>+++ b/net/vmw_vsock/virtio_transport.c
>@@ -624,8 +624,9 @@ static void virtio_transport_rx_work(struct work_struct *work)
> 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,12 +643,19 @@ static void virtio_transport_rx_work(struct work_struct *work)
> vsock->rx_buf_nr--;
>
> /* Drop short/long packets */
>- if (unlikely(len < sizeof(struct virtio_vsock_hdr) ||
>+ if (unlikely(len < sizeof(*hdr) ||
pre-existing: in some part we use sizeof(*hdr) in other
VIRTIO_VSOCK_SKB_HEADROOM, I think we should try to uniform that, but of
course not for this series!
> len > virtio_vsock_skb_len(skb))) {
> kfree_skb(skb);
> continue;
> }
>
>+ hdr = virtio_vsock_hdr(skb);
>+ payload_len = le32_to_cpu(hdr->len);
>+ if (payload_len > len - sizeof(*hdr)) {
Since this is an hot path, should we use `unlikely`, like in the
previous check, to instruct the branch predictor?
The rest LGTM!
Thanks,
Stefano
>+ kfree_skb(skb);
>+ continue;
>+ }
>+
> virtio_vsock_skb_rx_put(skb);
> virtio_transport_deliver_tap_pkt(skb);
> virtio_transport_recv_pkt(&virtio_transport, skb);
>--
>2.50.0.727.gbf7dc18ff4-goog
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-07-15 9:53 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20250714152103.6949-1-will@kernel.org>
2025-07-14 15:20 ` [PATCH v3 1/9] vhost/vsock: Avoid allocating arbitrarily-sized SKBs Will Deacon
2025-07-15 9:47 ` Stefano Garzarella
2025-07-14 15:20 ` [PATCH v3 2/9] vsock/virtio: Validate length in packet header before skb_put() Will Deacon
2025-07-15 9:53 ` Stefano Garzarella
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox