On Mon, Apr 20, 2026 at 03:20:51PM +0200, Stefano Garzarella wrote:
> From: Stefano Garzarella <[email protected]>
> 
> virtio_transport_init_zcopy_skb() uses iter->count as the size argument
> for msg_zerocopy_realloc(), which in turn passes it to
> mm_account_pinned_pages() for RLIMIT_MEMLOCK accounting. However, this
> function is called after virtio_transport_fill_skb() has already consumed
> the iterator via __zerocopy_sg_from_iter(), so on the last skb, iter->count
> will be 0, skipping the RLIMIT_MEMLOCK enforcement.
> 
> Pass pkt_len (the total bytes being sent) as an explicit parameter to
> virtio_transport_init_zcopy_skb() instead of reading the already-consumed
> iter->count.
> 
> This matches TCP and UDP, which both call msg_zerocopy_realloc() with
> the original message size.
> 
> Fixes: 581512a6dc93 ("vsock/virtio: MSG_ZEROCOPY flag support")
> Reported-by: Yiming Qian <[email protected]>
> Signed-off-by: Stefano Garzarella <[email protected]>
> ---
>  net/vmw_vsock/virtio_transport_common.c | 11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/net/vmw_vsock/virtio_transport_common.c 
> b/net/vmw_vsock/virtio_transport_common.c
> index 0742091beae7..416d533f493d 100644
> --- a/net/vmw_vsock/virtio_transport_common.c
> +++ b/net/vmw_vsock/virtio_transport_common.c
> @@ -73,6 +73,7 @@ static bool virtio_transport_can_zcopy(const struct 
> virtio_transport *t_ops,
>  static int virtio_transport_init_zcopy_skb(struct vsock_sock *vsk,
>                                          struct sk_buff *skb,
>                                          struct msghdr *msg,
> +                                        size_t pkt_len,
>                                          bool zerocopy)
>  {
>       struct ubuf_info *uarg;
> @@ -81,12 +82,10 @@ static int virtio_transport_init_zcopy_skb(struct 
> vsock_sock *vsk,
>               uarg = msg->msg_ubuf;
>               net_zcopy_get(uarg);
>       } else {
> -             struct iov_iter *iter = &msg->msg_iter;
>               struct ubuf_info_msgzc *uarg_zc;
>  
>               uarg = msg_zerocopy_realloc(sk_vsock(vsk),
> -                                         iter->count,
> -                                         NULL, false);
> +                                         pkt_len, NULL, false);
>               if (!uarg)
>                       return -1;
>  
> @@ -398,11 +397,17 @@ static int virtio_transport_send_pkt_info(struct 
> vsock_sock *vsk,
>                * each iteration. If this is last skb for this buffer
>                * and MSG_ZEROCOPY mode is in use - we must allocate
>                * completion for the current syscall.
> +              *
> +              * Pass pkt_len because msg iter is already consumed
> +              * by virtio_transport_fill_skb(), so iter->count
> +              * can not be used for RLIMIT_MEMLOCK pinned-pages
> +              * accounting done by msg_zerocopy_realloc().
>                */
>               if (info->msg && info->msg->msg_flags & MSG_ZEROCOPY &&
>                   skb_len == rest_len && info->op == VIRTIO_VSOCK_OP_RW) {
>                       if (virtio_transport_init_zcopy_skb(vsk, skb,
>                                                           info->msg,
> +                                                         pkt_len,
>                                                           can_zcopy)) {
>                               kfree_skb(skb);
>                               ret = -ENOMEM;
> -- 
> 2.53.0
> 

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

Reply via email to