Acquiring the access lock is not enough to ensure virtqueue's metadata such as vring pointers are valid.
The access status must also be checked. Fixes: c5736998305d ("vhost: fix missing virtqueue lock protection") Fixes: 830f7e790732 ("vhost: add non-blocking API for posting interrupt") Cc: sta...@dpdk.org Reported-by: Li Feng <fen...@smartx.com> Signed-off-by: Maxime Coquelin <maxime.coque...@redhat.com> --- lib/vhost/vhost.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/vhost/vhost.c b/lib/vhost/vhost.c index c03bb9c6eb..e9c775fa26 100644 --- a/lib/vhost/vhost.c +++ b/lib/vhost/vhost.c @@ -1328,6 +1328,7 @@ rte_vhost_vring_call(int vid, uint16_t vring_idx) { struct virtio_net *dev; struct vhost_virtqueue *vq; + int ret = 0; dev = get_device(vid); if (!dev) @@ -1342,14 +1343,20 @@ rte_vhost_vring_call(int vid, uint16_t vring_idx) rte_rwlock_read_lock(&vq->access_lock); + if (unlikely(!vq->access_ok)) { + ret = -1; + goto out_unlock; + } + if (vq_is_packed(dev)) vhost_vring_call_packed(dev, vq); else vhost_vring_call_split(dev, vq); +out_unlock: rte_rwlock_read_unlock(&vq->access_lock); - return 0; + return ret; } int @@ -1357,6 +1364,7 @@ rte_vhost_vring_call_nonblock(int vid, uint16_t vring_idx) { struct virtio_net *dev; struct vhost_virtqueue *vq; + int ret = 0; dev = get_device(vid); if (!dev) @@ -1372,14 +1380,20 @@ rte_vhost_vring_call_nonblock(int vid, uint16_t vring_idx) if (rte_rwlock_read_trylock(&vq->access_lock)) return -EAGAIN; + if (unlikely(!vq->access_ok)) { + ret = -1; + goto out_unlock; + } + if (vq_is_packed(dev)) vhost_vring_call_packed(dev, vq); else vhost_vring_call_split(dev, vq); +out_unlock: rte_rwlock_read_unlock(&vq->access_lock); - return 0; + return ret; } uint16_t -- 2.41.0