[v2,7/7] vhost: fix checking virtqueue access in stats API
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: be75dc99ea1f ("vhost: support per-virtqueue statistics")
Cc: stable@dpdk.org
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
lib/vhost/vhost.c | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
@@ -2199,6 +2199,7 @@ rte_vhost_vring_stats_get(int vid, uint16_t queue_id,
struct virtio_net *dev = get_device(vid);
struct vhost_virtqueue *vq;
unsigned int i;
+ int ret = VHOST_NB_VQ_STATS;
if (dev == NULL)
return -1;
@@ -2215,6 +2216,12 @@ rte_vhost_vring_stats_get(int vid, uint16_t queue_id,
vq = dev->virtqueue[queue_id];
rte_rwlock_write_lock(&vq->access_lock);
+
+ if (unlikely(!vq->access_ok)) {
+ ret = -1;
+ goto out_unlock;
+ }
+
for (i = 0; i < VHOST_NB_VQ_STATS; i++) {
/*
* No need to the read atomic counters as such, due to the
@@ -2224,15 +2231,18 @@ rte_vhost_vring_stats_get(int vid, uint16_t queue_id,
*(uint64_t *)(((char *)vq) + vhost_vq_stat_strings[i].offset);
stats[i].id = i;
}
+
+out_unlock:
rte_rwlock_write_unlock(&vq->access_lock);
- return VHOST_NB_VQ_STATS;
+ return ret;
}
int rte_vhost_vring_stats_reset(int vid, uint16_t queue_id)
{
struct virtio_net *dev = get_device(vid);
struct vhost_virtqueue *vq;
+ int ret = 0;
if (dev == NULL)
return -1;
@@ -2246,14 +2256,21 @@ int rte_vhost_vring_stats_reset(int vid, uint16_t queue_id)
vq = dev->virtqueue[queue_id];
rte_rwlock_write_lock(&vq->access_lock);
+
+ if (unlikely(!vq->access_ok)) {
+ ret = -1;
+ goto out_unlock;
+ }
/*
* No need to the reset atomic counters as such, due to the
* above write access_lock preventing them to be updated.
*/
memset(&vq->stats, 0, sizeof(vq->stats));
+
+out_unlock:
rte_rwlock_write_unlock(&vq->access_lock);
- return 0;
+ return ret;
}
int