Fix a possible dead loop which may happen, e.g. when driver created a loop in the desc list.
Fixes: b13ad2decc83 ("vhost: provide helpers for virtio ring relay") Signed-off-by: Tiwei Bie <tiwei....@intel.com> --- lib/librte_vhost/vdpa.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/librte_vhost/vdpa.c b/lib/librte_vhost/vdpa.c index 407d1c363..02083bb8a 100644 --- a/lib/librte_vhost/vdpa.c +++ b/lib/librte_vhost/vdpa.c @@ -157,6 +157,7 @@ rte_vdpa_relay_vring_avail(int vid, uint16_t qid, void *vring_m) struct vring_desc *idesc = NULL; struct vring *s_vring; uint64_t dlen; + uint32_t nr_descs; int ret; uint8_t perm; @@ -183,9 +184,14 @@ rte_vdpa_relay_vring_avail(int vid, uint16_t qid, void *vring_m) s_vring->avail->ring[idx_m & (vq->size - 1)] = desc_id; desc_ring = vq->desc; + nr_descs = vq->size; if (vq->desc[desc_id].flags & VRING_DESC_F_INDIRECT) { dlen = vq->desc[desc_id].len; + nr_descs = dlen / sizeof(struct vring_desc); + if (unlikely(nr_descs > vq->size)) + return -1; + desc_ring = (struct vring_desc *)(uintptr_t) vhost_iova_to_vva(dev, vq, vq->desc[desc_id].addr, &dlen, @@ -210,6 +216,8 @@ rte_vdpa_relay_vring_avail(int vid, uint16_t qid, void *vring_m) do { if (unlikely(desc_id >= vq->size)) goto fail; + if (unlikely(nr_descs-- == 0)) + goto fail; desc = desc_ring[desc_id]; perm = desc.flags & VRING_DESC_F_WRITE ? VHOST_ACCESS_WO : VHOST_ACCESS_RO; @@ -252,6 +260,7 @@ rte_vdpa_relay_vring_used(int vid, uint16_t qid, void *vring_m) struct vring_desc *idesc = NULL; struct vring *s_vring; uint64_t dlen; + uint32_t nr_descs; int ret; if (!dev || !vring_m) @@ -276,12 +285,17 @@ rte_vdpa_relay_vring_used(int vid, uint16_t qid, void *vring_m) desc_id = vq->used->ring[idx & (vq->size - 1)].id; desc_ring = vq->desc; + nr_descs = vq->size; if (unlikely(desc_id >= vq->size)) return -1; if (vq->desc[desc_id].flags & VRING_DESC_F_INDIRECT) { dlen = vq->desc[desc_id].len; + nr_descs = dlen / sizeof(struct vring_desc); + if (unlikely(nr_descs > vq->size)) + return -1; + desc_ring = (struct vring_desc *)(uintptr_t) vhost_iova_to_vva(dev, vq, vq->desc[desc_id].addr, &dlen, @@ -306,6 +320,8 @@ rte_vdpa_relay_vring_used(int vid, uint16_t qid, void *vring_m) do { if (unlikely(desc_id >= vq->size)) goto fail; + if (unlikely(nr_descs-- == 0)) + goto fail; desc = desc_ring[desc_id]; if (desc.flags & VRING_DESC_F_WRITE) vhost_log_write(dev, desc.addr, desc.len); -- 2.17.1