[dpdk-dev,v2,7/7] vhost: do sanity check for desc->next
Commit Message
A malicious guest may easily forge some illegal vring desc buf.
To make our vhost robust, we need make sure desc->next will not
go beyond the vq->desc[] array.
Suggested-by: Rich Lane <rich.lane@bigswitch.com>
Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
lib/librte_vhost/vhost_rxtx.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
Comments
On 2/18/2016 9:48 PM, Yuanhan Liu wrote:
> + if (unlikely(desc->next >= vq->size))
> + goto fail;
desc chains could be forged into a loop then vhost runs the dead loop
until it exhaust all mbuf memory.
On Mon, Mar 07, 2016 at 03:10:43AM +0000, Xie, Huawei wrote:
> On 2/18/2016 9:48 PM, Yuanhan Liu wrote:
> > + if (unlikely(desc->next >= vq->size))
> > + goto fail;
>
> desc chains could be forged into a loop then vhost runs the dead loop
> until it exhaust all mbuf memory.
Good point. Any elegant solution to avoid that?
--yliu
@@ -148,6 +148,8 @@ copy_mbuf_to_desc(struct virtio_net *dev, struct vhost_virtqueue *vq,
/* Room in vring buffer is not enough */
return -1;
}
+ if (unlikely(desc->next >= vq->size))
+ return -1;
desc = &vq->desc[desc->next];
desc_addr = gpa_to_vva(dev, desc->addr);
@@ -302,7 +304,7 @@ fill_vec_buf(struct vhost_virtqueue *vq, uint32_t avail_idx,
uint32_t len = *allocated;
while (1) {
- if (vec_id >= BUF_VECTOR_MAX)
+ if (unlikely(vec_id >= BUF_VECTOR_MAX || idx >= vq->size))
return -1;
len += vq->desc[idx].len;
@@ -671,6 +673,8 @@ copy_desc_to_mbuf(struct virtio_net *dev, struct vhost_virtqueue *vq,
while (desc_avail || (desc->flags & VRING_DESC_F_NEXT) != 0) {
/* This desc reachs to its end, get the next one */
if (desc_avail == 0) {
+ if (unlikely(desc->next >= vq->size))
+ goto fail;
desc = &vq->desc[desc->next];
desc_addr = gpa_to_vva(dev, desc->addr);
@@ -691,9 +695,7 @@ copy_desc_to_mbuf(struct virtio_net *dev, struct vhost_virtqueue *vq,
if (unlikely(!cur)) {
RTE_LOG(ERR, VHOST_DATA, "Failed to "
"allocate memory for mbuf.\n");
- if (head)
- rte_pktmbuf_free(head);
- return NULL;
+ goto fail;
}
if (!head) {
head = cur;
@@ -729,6 +731,11 @@ copy_desc_to_mbuf(struct virtio_net *dev, struct vhost_virtqueue *vq,
}
return head;
+
+fail:
+ if (head)
+ rte_pktmbuf_free(head);
+ return NULL;
}
uint16_t