From: Tiwei Bie Date: Fri, 4 Jan 2019 04:06:39 +0000 (+0800) Subject: vhost: fix possible dead loop in relay helpers X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=4e282bc6c531c74f3144f5e422fc51fe82b71a27;p=dpdk.git vhost: fix possible dead loop in relay helpers 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 Reviewed-by: Maxime Coquelin --- diff --git a/lib/librte_vhost/vdpa.c b/lib/librte_vhost/vdpa.c index 407d1c363f..02083bb8ad 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);