From nobody Fri Jun 12 14:18:15 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3FEBD3A5420 for ; Thu, 14 May 2026 09:29:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778750996; cv=none; b=eTYpDOsVzojR3WBXy81JAsmSaip5BFR7cfLgWeAlAPZmgwIKR66XF8QgQ4CItDjZM/TrBOja4JAQHfSqhhcbK/5OAZxAUF1qBliFyAUPvcw70WmLaWHrNcqi/6jk/Xlmebp5APC3dQg/hGWWZtSynKuvuCA2QoqH8xpjVQeuQ3w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778750996; c=relaxed/simple; bh=giBrJRQN2VMMjCh/yoL5SJRMxEqzegUg6O8u4pivPpg=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=IxZUHMjweGbs4HA/wPAM07GO43vuyt5inFM+JZnmNS5kg18FM4eZofzTPpQcp2wL61Ikm7Cy+wqYrAb2feWX7/xqnB8bExVW+z4tJ2pOhUTMnmZucYrijJ2lLCpKBKTySgJHh5Mx+FKz1+4LDjZF27+8Spz9fT6Zfiuu8Q3kD7g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=CqHmrock; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b=OzhzmzkI; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="CqHmrock"; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b="OzhzmzkI" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1778750994; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=X7d0CywKsZQfA/8iHBsstOBzlQ/bG9Xhxh5p1dy0nCs=; b=CqHmrockUf/NL4EU8+A9D6jsxXFfXxgSLQEnH2nSjjk71gVOh+J2/wunMfFLVkCNFSauvx bqDJ53zI0qyvZYcyVqTzQ9VNojCgIjwaRoXo7A6/0LRxxVTz1c5juy9FoMwb5BspUvLYSL dI0bnWOg3ESd6NW+EmhQjg+Jyf655Nw= Received: from mail-wm1-f70.google.com (mail-wm1-f70.google.com [209.85.128.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-682-4wzpK8bLOU6whOsLu9y_sA-1; Thu, 14 May 2026 05:29:53 -0400 X-MC-Unique: 4wzpK8bLOU6whOsLu9y_sA-1 X-Mimecast-MFC-AGG-ID: 4wzpK8bLOU6whOsLu9y_sA_1778750992 Received: by mail-wm1-f70.google.com with SMTP id 5b1f17b1804b1-48a589c7879so66339575e9.1 for ; Thu, 14 May 2026 02:29:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=google; t=1778750992; x=1779355792; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=X7d0CywKsZQfA/8iHBsstOBzlQ/bG9Xhxh5p1dy0nCs=; b=OzhzmzkI+J9OzBIERCrgLc7zkdxsS+Jnx0q2QIrIDnwfmsZ3CJDGapprCN8gJXAbGh W30pTa+BBTNoL20DvZHYJupUsT8x7rNdQhkXddKbRLBxGhbn07unB2JcqlkOjKyFTtZL sWrhyVQ3se4gdTBo5e7kARVWvGMt7vKLCpSomROyuJ4v0SjhX5Y1PTx3wDlFnEGtzYWw /XdgC3hEypLZqI6YJnJqF8SU3B3qKVo0JSSPwQilOtCfyYsJ/15OSnauUjGHf3PxuTb9 bF3yKynoebOnygYyVE6wlDwiNEIruHb+cZuRt/rmULoJZKszsAWfsXp7zaurayFd7eH2 BNcw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778750992; x=1779355792; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=X7d0CywKsZQfA/8iHBsstOBzlQ/bG9Xhxh5p1dy0nCs=; b=h8es4Mgh/QpTGXYTgXzFt88gHasb/PZ3jA8lYeakeh2r/s++EOcxCZnttX6QDPsYd5 JfNeVYbLWQW9jmVMMflefGlyK49MMnPRCwSWVOA04uCWIKzeJuiJW1Kn0JJOOVEkFaYX tN7C1fNbJbXROHW29Yr3fb2VTprAcrZmu829r1sKx7rhTpNbdK7L0BPW9CJ03JfmuzvC cGKob4e39eqBHmFuE2k6DqGIwe0d3boidHiDLRu0QSl+4G5k0nSkm+YuyXdpMq+RBK3E 1tC/cWEkq5aZi5kxA+7t2mP54cA4wrLsf10TAx1tzZ7QVtNjckIzyspfFmBrxK/HoBZU cJkg== X-Forwarded-Encrypted: i=1; AFNElJ/Z79gdb798NLqV3Irx6tLJg6kzjKWNG9FbFJL8P3RPzqPMeerwenRvdpg5yT+c3X/QGn6SYj9/tcVhKsA=@vger.kernel.org X-Gm-Message-State: AOJu0YyRPd2KueyspYg0kiYzt4h/b+lRHUJcT9nY7BgyfiFRzfE+q49M 7FgmsqxijUuTKqHULgN8F7unaaFS6yv4smQpT/pOEDP503VDQXAbIC8rZOjB/Ks/MS7u2rkZI8U C/qSv6lPnJEht32Eo+PTvQNepQonHrNyaPLm/sFI2gwoMKwzzYE/Fo+VkvVDpg+J0uA== X-Gm-Gg: Acq92OFkSKDdwAW0pWDjLiPrgx2PtDtoAW3MbqYm1BaPaGVaRGrUbbpfp3fkB151MB3 oJ/GGIvXn4fvXk4f/8z+Y4bAYlrAcsPp++yCsIpFvKoKJCVYOulyWdYZeM8lzYtjVeLOPL6ecPU /fzdg8hhKxrZwhmcBbnyhMhgb02IEfEq7bERIHuHPGdmVFyC3Gzivn/wK7X03qEhYEJkrDr56LD 2LMXrQBvjQKQC6EwSImH5dKfkotkeIw88JhG0Hzxh1RzT2Q71cZR3yIfW7mabrIhl8xt6kFVF3z lwQgg4bHrqLMHR0JtZpDeIQL1c1QY0u0djk8yTgPwgGFCwsoVDsRJuTbqn9KLPEoYiu7XxOrchQ I97EDB3PiGprZ8hWIw/Mdy6uGJmsPvdz+G2EHeHwdJyxAslo6yftZvLiBYCAzCgFI/DxDaxs= X-Received: by 2002:a05:600c:a305:b0:485:3cef:d6ea with SMTP id 5b1f17b1804b1-48fe24960bemr2343525e9.13.1778750991752; Thu, 14 May 2026 02:29:51 -0700 (PDT) X-Received: by 2002:a05:600c:a305:b0:485:3cef:d6ea with SMTP id 5b1f17b1804b1-48fe24960bemr2343285e9.13.1778750991254; Thu, 14 May 2026 02:29:51 -0700 (PDT) Received: from stex1 (host-87-16-204-231.retail.telecomitalia.it. [87.16.204.231]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48fd7672ae9sm19873735e9.6.2026.05.14.02.29.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 14 May 2026 02:29:50 -0700 (PDT) From: Stefano Garzarella To: netdev@vger.kernel.org Cc: Jakub Kicinski , Paolo Abeni , Simon Horman , Arseniy Krasnov , Stefan Hajnoczi , Stefano Garzarella , kvm@vger.kernel.org, Eric Dumazet , =?UTF-8?q?Eugenio=20P=C3=A9rez?= , "Michael S. Tsirkin" , Xuan Zhuo , virtualization@lists.linux.dev, "David S. Miller" , Jason Wang , linux-kernel@vger.kernel.org, Maher Azzouzi Subject: [PATCH net] vsock/virtio: fix zerocopy completion for multi-skb sends Date: Thu, 14 May 2026 11:29:48 +0200 Message-ID: <20260514092948.268720-1-sgarzare@redhat.com> X-Mailer: git-send-email 2.54.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Stefano Garzarella When a large message is fragmented into multiple skbs, the zerocopy uarg is only allocated and attached to the last skb in the loop. Non-final skbs carry pinned user pages with no completion tracking, so the kernel has no way to notify userspace when those pages are safe to reuse. If the loop breaks early the uarg is never allocated at all, leaking pinned pages with no completion notification. Fix this by following the approach used by TCP: allocate the zerocopy uarg (if not provided by the caller) before the send loop and attach it to every skb via skb_zcopy_set(), which takes a reference per skb. Each skb's completion properly decrements the refcount, and the notification only fires after the last skb is freed. On failure, if no data was sent, the uarg is cleanly aborted via net_zcopy_put_abort(). This issue was initially discovered by sashiko while reviewing commit 1cb36e252211 ("vsock/virtio: fix MSG_ZEROCOPY pinned-pages accounting") but was pre-existing. Fixes: 581512a6dc93 ("vsock/virtio: MSG_ZEROCOPY flag support") Cc: Arseniy Krasnov Closes: https://sashiko.dev/#/patchset/20260420132051.217589-1-sgarzare%40r= edhat.com Reported-by: Maher Azzouzi Signed-off-by: Stefano Garzarella Acked-by: Arseniy Krasnov Acked-by: Michael S. Tsirkin --- net/vmw_vsock/virtio_transport_common.c | 83 ++++++++++--------------- 1 file changed, 34 insertions(+), 49 deletions(-) diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio= _transport_common.c index 989cc252d3d3..1e3409d28164 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c @@ -70,34 +70,6 @@ static bool virtio_transport_can_zcopy(const struct virt= io_transport *t_ops, return true; } =20 -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; - - if (msg->msg_ubuf) { - uarg =3D msg->msg_ubuf; - net_zcopy_get(uarg); - } else { - struct ubuf_info_msgzc *uarg_zc; - - uarg =3D msg_zerocopy_realloc(sk_vsock(vsk), - pkt_len, NULL, false); - if (!uarg) - return -1; - - uarg_zc =3D uarg_to_msgzc(uarg); - uarg_zc->zerocopy =3D zerocopy ? 1 : 0; - } - - skb_zcopy_init(skb, uarg); - - return 0; -} - static int virtio_transport_fill_skb(struct sk_buff *skb, struct virtio_vsock_pkt_info *info, size_t len, @@ -317,8 +289,10 @@ static int virtio_transport_send_pkt_info(struct vsock= _sock *vsk, u32 src_cid, src_port, dst_cid, dst_port; const struct virtio_transport *t_ops; struct virtio_vsock_sock *vvs; + struct ubuf_info *uarg =3D NULL; u32 pkt_len =3D info->pkt_len; bool can_zcopy =3D false; + bool have_uref =3D false; u32 rest_len; int ret; =20 @@ -360,6 +334,25 @@ static int virtio_transport_send_pkt_info(struct vsock= _sock *vsk, if (can_zcopy) max_skb_len =3D min_t(u32, VIRTIO_VSOCK_MAX_PKT_BUF_SIZE, (MAX_SKB_FRAGS * PAGE_SIZE)); + + if (info->msg->msg_flags & MSG_ZEROCOPY && + info->op =3D=3D VIRTIO_VSOCK_OP_RW) { + uarg =3D info->msg->msg_ubuf; + + if (!uarg) { + uarg =3D msg_zerocopy_realloc(sk_vsock(vsk), + pkt_len, NULL, false); + if (!uarg) { + virtio_transport_put_credit(vvs, pkt_len); + return -ENOMEM; + } + + if (!can_zcopy) + uarg_to_msgzc(uarg)->zerocopy =3D 0; + + have_uref =3D true; + } + } } =20 rest_len =3D pkt_len; @@ -378,27 +371,7 @@ static int virtio_transport_send_pkt_info(struct vsock= _sock *vsk, break; } =20 - /* We process buffer part by part, allocating skb on - * 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 =3D=3D rest_len && info->op =3D=3D VIRTIO_VSOCK_OP_RW) { - if (virtio_transport_init_zcopy_skb(vsk, skb, - info->msg, - pkt_len, - can_zcopy)) { - kfree_skb(skb); - ret =3D -ENOMEM; - break; - } - } + skb_zcopy_set(skb, uarg, NULL); =20 virtio_transport_inc_tx_pkt(vvs, skb); =20 @@ -422,6 +395,18 @@ static int virtio_transport_send_pkt_info(struct vsock= _sock *vsk, =20 virtio_transport_put_credit(vvs, rest_len); =20 + /* msg_zerocopy_realloc() initializes the ubuf_info refcnt to 1. + * skb_zcopy_set() increases it for each skb, so we can drop that + * initial reference to keep it balanced. + */ + if (have_uref) { + if (rest_len =3D=3D pkt_len) + /* No data sent, abort the notification. */ + net_zcopy_put_abort(uarg, true); + else + net_zcopy_put(uarg); + } + /* Return number of bytes, if any data has been sent. */ if (rest_len !=3D pkt_len) ret =3D pkt_len - rest_len; --=20 2.54.0