Skip to content

Commit

Permalink
kvm tools: net: don't propagate error codes from tx/rx operations
Browse files Browse the repository at this point in the history
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@arm.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
  • Loading branch information
wildea01 committed Jun 1, 2015
1 parent 385ebc4 commit 6d6cc14
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 5 deletions.
2 changes: 1 addition & 1 deletion net/uip/core.c
Expand Up @@ -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++) {
Expand Down
20 changes: 16 additions & 4 deletions virtio/net.c
Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -131,6 +137,7 @@ static void *virtio_net_rx_thread(void *p)
}
}

out_err:
pthread_exit(NULL);
return NULL;

Expand Down Expand Up @@ -165,17 +172,22 @@ 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);
}

if (virtio_queue__should_signal(vq))
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)
Expand Down

0 comments on commit 6d6cc14

Please sign in to comment.