Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f1f4a514 authored by Yunjian Wang's avatar Yunjian Wang Committed by Greg Kroah-Hartman
Browse files

vhost_net: fix ubuf refcount incorrectly when sendmsg fails



[ Upstream commit 01e31bea7e622f1890c274f4aaaaf8bccd296aa5 ]

Currently the vhost_zerocopy_callback() maybe be called to decrease
the refcount when sendmsg fails in tun. The error handling in vhost
handle_tx_zerocopy() will try to decrease the same refcount again.
This is wrong. To fix this issue, we only call vhost_net_ubuf_put()
when vq->heads[nvq->desc].len == VHOST_DMA_IN_PROGRESS.

Fixes: bab632d6 ("vhost: vhost TX zero-copy support")
Signed-off-by: default avatarYunjian Wang <wangyunjian@huawei.com>
Acked-by: default avatarWillem de Bruijn <willemb@google.com>
Acked-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Acked-by: default avatarJason Wang <jasowang@redhat.com>
Link: https://lore.kernel.org/r/1609207308-20544-1-git-send-email-wangyunjian@huawei.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 2e9e8bc3
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -377,6 +377,7 @@ static void handle_tx(struct vhost_net *net)
	size_t hdr_size;
	struct socket *sock;
	struct vhost_net_ubuf_ref *uninitialized_var(ubufs);
	struct ubuf_info *ubuf;
	bool zcopy, zcopy_used;
	int sent_pkts = 0;

@@ -444,9 +445,7 @@ static void handle_tx(struct vhost_net *net)

		/* use msg_control to pass vhost zerocopy ubuf info to skb */
		if (zcopy_used) {
			struct ubuf_info *ubuf;
			ubuf = nvq->ubuf_info + nvq->upend_idx;

			vq->heads[nvq->upend_idx].id = cpu_to_vhost32(vq, head);
			vq->heads[nvq->upend_idx].len = VHOST_DMA_IN_PROGRESS;
			ubuf->callback = vhost_zerocopy_callback;
@@ -465,6 +464,7 @@ static void handle_tx(struct vhost_net *net)
		err = sock->ops->sendmsg(sock, &msg, len);
		if (unlikely(err < 0)) {
			if (zcopy_used) {
				if (vq->heads[ubuf->desc].len == VHOST_DMA_IN_PROGRESS)
					vhost_net_ubuf_put(ubufs);
				nvq->upend_idx = ((unsigned)nvq->upend_idx - 1)
					% UIO_MAXIOV;