From d767436ee5d26d1d417ae17d1a2a47879bf632a6 Mon Sep 17 00:00:00 2001 From: Tiwei Bie Date: Fri, 22 Feb 2019 10:42:07 +0800 Subject: [PATCH] vhost: fix potential use-after-free for zero copy mbuf Don't free the zero copy mbufs before they have been consumed, otherwise there could be use-after-free. Fixes: b0a985d1f340 ("vhost: add dequeue zero copy") Cc: stable@dpdk.org Signed-off-by: Tiwei Bie Reviewed-by: Maxime Coquelin --- lib/librte_vhost/vhost.h | 12 ++++++++++++ lib/librte_vhost/vhost_user.c | 3 +++ lib/librte_vhost/virtio_net.c | 12 ------------ 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h index bcfce274b7..044651b199 100644 --- a/lib/librte_vhost/vhost.h +++ b/lib/librte_vhost/vhost.h @@ -757,4 +757,16 @@ restore_mbuf(struct rte_mbuf *m) } } +static __rte_always_inline bool +mbuf_is_consumed(struct rte_mbuf *m) +{ + while (m) { + if (rte_mbuf_refcnt_read(m) > 1) + return false; + m = m->next; + } + + return true; +} + #endif /* _VHOST_NET_CDEV_H_ */ diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c index e3ddf25891..6d82535149 100644 --- a/lib/librte_vhost/vhost_user.c +++ b/lib/librte_vhost/vhost_user.c @@ -1218,6 +1218,9 @@ free_zmbufs(struct vhost_virtqueue *vq) zmbuf != NULL; zmbuf = next) { next = TAILQ_NEXT(zmbuf, next); + while (!mbuf_is_consumed(zmbuf->mbuf)) + usleep(1000); + restore_mbuf(zmbuf->mbuf); rte_pktmbuf_free(zmbuf->mbuf); TAILQ_REMOVE(&vq->zmbuf_list, zmbuf, next); diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c index 862ca5e1af..40a2923640 100644 --- a/lib/librte_vhost/virtio_net.c +++ b/lib/librte_vhost/virtio_net.c @@ -1306,18 +1306,6 @@ get_zmbuf(struct vhost_virtqueue *vq) return NULL; } -static __rte_always_inline bool -mbuf_is_consumed(struct rte_mbuf *m) -{ - while (m) { - if (rte_mbuf_refcnt_read(m) > 1) - return false; - m = m->next; - } - - return true; -} - static __rte_always_inline uint16_t virtio_dev_tx_split(struct virtio_net *dev, struct vhost_virtqueue *vq, struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count)