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: sta...@dpdk.org Signed-off-by: Tiwei Bie <tiwei....@intel.com> --- 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 bcfce274b..044651b19 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 e3ddf2589..6d8253514 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 862ca5e1a..40a292364 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) -- 2.17.1