From 14962a9c4f55b1a476246f279e999b555f78bbbe Mon Sep 17 00:00:00 2001 From: Tiwei Bie Date: Wed, 25 Jul 2018 21:51:37 +0800 Subject: [PATCH] vhost: fix overflow on shadow used ring The shadow used ring's size is the same as the vq's size, so we shouldn't try more than "vq size" times. Besides, the element pointed by avail->idx isn't available to the device, so we will return error when try "vq size" times. Fixes: 24e4844048e1 ("vhost: unify Rx mergeable and non-mergeable paths") Fixes: a922401f35cc ("vhost: add Rx support for packed ring") Signed-off-by: Tiwei Bie Reviewed-by: Jens Freimann --- lib/librte_vhost/virtio_net.c | 37 ++++++++++++++++------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c index a8b4c961cc..5779bcf53a 100644 --- a/lib/librte_vhost/virtio_net.c +++ b/lib/librte_vhost/virtio_net.c @@ -415,13 +415,20 @@ reserve_avail_buf_split(struct virtio_net *dev, struct vhost_virtqueue *vq, cur_idx = vq->last_avail_idx; if (rxvq_is_mergeable(dev)) - max_tries = vq->size; + max_tries = vq->size - 1; else max_tries = 1; while (size > 0) { if (unlikely(cur_idx == avail_head)) return -1; + /* + * if we tried all available ring items, and still + * can't get enough buf, it means something abnormal + * happened. + */ + if (unlikely(++tries > max_tries)) + return -1; if (unlikely(fill_vec_buf_split(dev, vq, cur_idx, &vec_idx, buf_vec, @@ -433,16 +440,7 @@ reserve_avail_buf_split(struct virtio_net *dev, struct vhost_virtqueue *vq, size -= len; cur_idx++; - tries++; *num_buffers += 1; - - /* - * if we tried all available ring items, and still - * can't get enough buf, it means something abnormal - * happened. - */ - if (unlikely(tries > max_tries)) - return -1; } *nr_vec = vec_idx; @@ -582,11 +580,19 @@ reserve_avail_buf_packed(struct virtio_net *dev, struct vhost_virtqueue *vq, avail_idx = vq->last_avail_idx; if (rxvq_is_mergeable(dev)) - max_tries = vq->size; + max_tries = vq->size - 1; else max_tries = 1; while (size > 0) { + /* + * if we tried all available ring items, and still + * can't get enough buf, it means something abnormal + * happened. + */ + if (unlikely(++tries > max_tries)) + return -1; + if (unlikely(fill_vec_buf_packed(dev, vq, avail_idx, &desc_count, buf_vec, &vec_idx, @@ -603,16 +609,7 @@ reserve_avail_buf_packed(struct virtio_net *dev, struct vhost_virtqueue *vq, avail_idx -= vq->size; *nr_descs += desc_count; - tries++; *num_buffers += 1; - - /* - * if we tried all available ring items, and still - * can't get enough buf, it means something abnormal - * happened. - */ - if (unlikely(tries > max_tries)) - return -1; } *nr_vec = vec_idx; -- 2.20.1