On Fri, May 08, 2026 at 06:44:11PM +0200, Stefano Garzarella wrote:
> From: Stefano Garzarella <[email protected]>
> 
> For non-linear skbs, virtio_transport_build_skb() goes through
> virtio_transport_copy_nonlinear_skb() to copy the original payload
> in the new skb to be delivered to the vsockmon tap device.
> This manually initializes an iov_iter but does not set iov_iter.count.
> Since the iov_iter is zero-initialized, the copy length is zero and no
> payload is actually copied to the monitor interface, leaving data
> un-initialized.
> 
> Fix this by removing the linear vs non-linear split and using
> skb_copy_datagram_iter() with iov_iter_kvec() for all cases, as
> vhost-vsock already does. This handles both linear and non-linear skbs,
> properly initializes the iov_iter, and removes the now unused
> virtio_transport_copy_nonlinear_skb().
> 
> While touching this code, let's also check the return value of
> skb_copy_datagram_iter(), even though it's unlikely to fail.
> 
> Fixes: 4b0bf10eb077 ("vsock/virtio: non-linear skb handling for tap")
> Reported-by: Yiqi Sun <[email protected]>
> Signed-off-by: Stefano Garzarella <[email protected]>
> ---
>  net/vmw_vsock/virtio_transport_common.c | 40 ++++++++-----------------
>  1 file changed, 12 insertions(+), 28 deletions(-)
> 
> diff --git a/net/vmw_vsock/virtio_transport_common.c 
> b/net/vmw_vsock/virtio_transport_common.c
> index a678d5d75704..989cc252d3d3 100644
> --- a/net/vmw_vsock/virtio_transport_common.c
> +++ b/net/vmw_vsock/virtio_transport_common.c
> @@ -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)
>  {
> @@ -214,13 +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);
> -
> -                     virtio_transport_copy_nonlinear_skb(pkt, data, 
> payload_len);
> -             } else {
> -                     skb_put_data(skb, pkt->data + 
> VIRTIO_VSOCK_SKB_CB(pkt)->offset,
> -                                  payload_len);
> +             struct iov_iter iov_iter;
> +             struct kvec kvec;
> +             void *data = skb_put(skb, 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;
>               }
>       }
>  
> -- 
> 2.54.0
> 

Reviewed-by: Bobby Eshleman <[email protected]>

Reply via email to