[v2,1/7] vhost: fix missing vring call check on virtqueue access
Checks
Commit Message
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: 6c299bb7322f ("vhost: introduce vring call API")
Fixes: c5736998305d ("vhost: fix missing virtqueue lock protection")
Fixes: 830f7e790732 ("vhost: add non-blocking API for posting interrupt")
Cc: stable@dpdk.org
Reported-by: Li Feng <fengli@smartx.com>
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
lib/vhost/vhost.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
@@ -1330,6 +1330,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)
@@ -1344,14 +1345,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
@@ -1359,6 +1366,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)
@@ -1374,14 +1382,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