[PATCH 03/17] kvm tools: net: don't propagate error codes from tx/rx operations

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Currently, if a ->tx or ->rx callback into the net_dev_operations
encounters an error, it returns -1 to the virtio-net code, which in turn
treats this as an unsigned (size_t) size describing the data available.
The resulting memcpy operation then quickly explodes with a SEGV.

This patch detects the error code from the low-level callbacks and
exits the thread dealing with the erroneous queue.

Signed-off-by: Will Deacon <will.deacon@xxxxxxx>
---
 tools/kvm/net/uip/core.c |  2 +-
 tools/kvm/virtio/net.c   | 20 ++++++++++++++++----
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/tools/kvm/net/uip/core.c b/tools/kvm/net/uip/core.c
index b3cd8c25d4da..e860f3afec97 100644
--- a/tools/kvm/net/uip/core.c
+++ b/tools/kvm/net/uip/core.c
@@ -36,7 +36,7 @@ int uip_tx(struct iovec *iov, u16 out, struct uip_info *info)
 
 		buf = malloc(eth_len);
 		if (!buf)
-			return -1;
+			return -ENOMEM;
 
 		eth = (struct uip_eth *)buf;
 		for (i = 1; i < out; i++) {
diff --git a/tools/kvm/virtio/net.c b/tools/kvm/virtio/net.c
index 2f61718a5029..ae4712c3c550 100644
--- a/tools/kvm/virtio/net.c
+++ b/tools/kvm/virtio/net.c
@@ -81,7 +81,7 @@ static void *virtio_net_rx_thread(void *p)
 	struct net_dev *ndev = p;
 	u16 out, in;
 	u16 head;
-	size_t len, copied;
+	int len, copied;
 	u32 id;
 
 	mutex_lock(&ndev->mutex);
@@ -108,11 +108,17 @@ static void *virtio_net_rx_thread(void *p)
 			struct virtio_net_hdr_mrg_rxbuf *hdr;
 
 			len = ndev->ops->rx(&dummy_iov, 1, ndev);
+			if (len < 0) {
+				pr_warning("%s: rx on vq %u failed (%d), exiting thread\n",
+						__func__, id, len);
+				goto out_err;
+			}
+
 			copied = 0;
 			head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
 			hdr = (void *)iov[0].iov_base;
 			while (copied < len) {
-				size_t iovsize = min(len - copied, iov_size(iov, in));
+				size_t iovsize = min_t(size_t, len - copied, iov_size(iov, in));
 
 				memcpy_toiovec(iov, buffer + copied, iovsize);
 				copied += iovsize;
@@ -131,6 +137,7 @@ static void *virtio_net_rx_thread(void *p)
 		}
 	}
 
+out_err:
 	pthread_exit(NULL);
 	return NULL;
 
@@ -165,6 +172,12 @@ static void *virtio_net_tx_thread(void *p)
 		while (virt_queue__available(vq)) {
 			head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
 			len = ndev->ops->tx(iov, out, ndev);
+			if (len < 0) {
+				pr_warning("%s: tx on vq %u failed (%d)\n",
+						__func__, id, len);
+				goto out_err;
+			}
+
 			virt_queue__set_used_elem(vq, head, len);
 		}
 
@@ -172,10 +185,9 @@ static void *virtio_net_tx_thread(void *p)
 			ndev->vdev.ops->signal_vq(kvm, &ndev->vdev, id);
 	}
 
+out_err:
 	pthread_exit(NULL);
-
 	return NULL;
-
 }
 
 static virtio_net_ctrl_ack virtio_net_handle_mq(struct kvm* kvm, struct net_dev *ndev, struct virtio_net_ctrl_hdr *ctrl)
-- 
1.8.2.2

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux