Re: [PATCH net] vsock/virtio: fix MSG_ZEROCOPY pinned-pages accounting
From: Bobby Eshleman
Date: Mon Apr 20 2026 - 14:37:02 EST
On Mon, Apr 20, 2026 at 03:20:51PM +0200, Stefano Garzarella wrote:
> From: Stefano Garzarella <sgarzare@xxxxxxxxxx>
>
> 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 <yimingqian591@xxxxxxxxx>
> Signed-off-by: Stefano Garzarella <sgarzare@xxxxxxxxxx>
> ---
> 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 <bobbyeshleman@xxxxxxxx>