]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
vsock/virtio: fix MSG_ZEROCOPY pinned-pages accounting
authorStefano Garzarella <sgarzare@redhat.com>
Mon, 20 Apr 2026 13:20:51 +0000 (15:20 +0200)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 23 Apr 2026 11:03:21 +0000 (13:03 +0200)
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@gmail.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Reviewed-by: Bobby Eshleman <bobbyeshleman@meta.com>
Link: https://patch.msgid.link/20260420132051.217589-1-sgarzare@redhat.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
net/vmw_vsock/virtio_transport_common.c

index 0742091beae7cf74f4cc3dbf5054a456b64ab2cf..416d533f493d7b07e9c77c43f741d28cfcd0953e 100644 (file)
@@ -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;