Merge branch 'vsock-virtio-fix-vsockmon-tap-skb-construction'

Stefano Garzarella says:

====================
vsock/virtio: fix vsockmon tap skb construction

While reviewing the patch posted by Yiqi Sun [1] to fix an issue in
virtio_transport_build_skb(), I discovered another issue related to
the offset and length of the payload to be copied in the new skb.
This was introduced when we did the skb conversion, and fixed by
patch 1.

Patch 2 fixes the issue found by Yiqi Sun in a different way: using
iov_iter_kvec() to properly initialize all the iov_iter fields and
removing the linear vs non-linear split like we alredy do in
vhost-vsock.

It could have been a single patch, but since there were two affected
commits, I decided to keep the fixes separate.

[1] https://lore.kernel.org/netdev/20260430071110.380509-1-sunyiqixm@gmail.com/
====================

Link: https://patch.msgid.link/20260508164411.261440-1-sgarzare@redhat.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Paolo Abeni
2026-05-12 12:52:17 +02:00

View File

@@ -136,27 +136,6 @@ static void virtio_transport_init_hdr(struct sk_buff *skb,
hdr->fwd_cnt = cpu_to_le32(0);
}
static void virtio_transport_copy_nonlinear_skb(const struct sk_buff *skb,
void *dst,
size_t len)
{
struct iov_iter iov_iter = { 0 };
struct kvec kvec;
size_t to_copy;
kvec.iov_base = dst;
kvec.iov_len = len;
iov_iter.iter_type = ITER_KVEC;
iov_iter.kvec = &kvec;
iov_iter.nr_segs = 1;
to_copy = min_t(size_t, len, skb->len);
skb_copy_datagram_iter(skb, VIRTIO_VSOCK_SKB_CB(skb)->offset,
&iov_iter, to_copy);
}
/* Packet capture */
static struct sk_buff *virtio_transport_build_skb(void *opaque)
{
@@ -166,12 +145,12 @@ static struct sk_buff *virtio_transport_build_skb(void *opaque)
struct sk_buff *skb;
size_t payload_len;
/* A packet could be split to fit the RX buffer, so we can retrieve
* the payload length from the header and the buffer pointer taking
* care of the offset in the original packet.
/* A packet could be split to fit the RX buffer, so we use
* the payload length from the header, which has been updated
* by the sender to reflect the fragment size.
*/
pkt_hdr = virtio_vsock_hdr(pkt);
payload_len = pkt->len;
payload_len = le32_to_cpu(pkt_hdr->len);
skb = alloc_skb(sizeof(*hdr) + sizeof(*pkt_hdr) + payload_len,
GFP_ATOMIC);
@@ -214,12 +193,18 @@ static struct sk_buff *virtio_transport_build_skb(void *opaque)
skb_put_data(skb, pkt_hdr, sizeof(*pkt_hdr));
if (payload_len) {
if (skb_is_nonlinear(pkt)) {
void *data = skb_put(skb, payload_len);
struct iov_iter iov_iter;
struct kvec kvec;
void *data = skb_put(skb, payload_len);
virtio_transport_copy_nonlinear_skb(pkt, data, payload_len);
} else {
skb_put_data(skb, pkt->data, payload_len);
kvec.iov_base = data;
kvec.iov_len = payload_len;
iov_iter_kvec(&iov_iter, ITER_DEST, &kvec, 1, payload_len);
if (skb_copy_datagram_iter(pkt, VIRTIO_VSOCK_SKB_CB(pkt)->offset,
&iov_iter, payload_len)) {
kfree_skb(skb);
return NULL;
}
}