From 0a8363efdbeb92446d0fc1f11788a76f8b969daf Mon Sep 17 00:00:00 2001 From: Maxime Coquelin Date: Wed, 11 May 2022 08:58:37 +0200 Subject: [PATCH] vhost: add runtime locking check in unsafe API This patch adds runtime checks in unsafe Vhost async APIs, to ensure the access lock is taken. The detection won't work every time, as another thread could take the lock, but it would help to detect misuse of these unsafe API. Signed-off-by: Maxime Coquelin Reviewed-by: David Marchand Reviewed-by: Jiayu Hu Reviewed-by: Chenbo Xia --- lib/vhost/vhost.c | 18 ++++++++++++++++++ lib/vhost/virtio_net.c | 6 ++++++ 2 files changed, 24 insertions(+) diff --git a/lib/vhost/vhost.c b/lib/vhost/vhost.c index 3537680107..b14521e4d1 100644 --- a/lib/vhost/vhost.c +++ b/lib/vhost/vhost.c @@ -1769,6 +1769,12 @@ rte_vhost_async_channel_register_thread_unsafe(int vid, uint16_t queue_id) if (unlikely(vq == NULL || !dev->async_copy)) return -1; + if (unlikely(!rte_spinlock_is_locked(&vq->access_lock))) { + VHOST_LOG_CONFIG(ERR, "(%s) %s() called without access lock taken.\n", + dev->ifname, __func__); + return -1; + } + return async_channel_register(vid, queue_id); } @@ -1829,6 +1835,12 @@ rte_vhost_async_channel_unregister_thread_unsafe(int vid, uint16_t queue_id) if (vq == NULL) return -1; + if (unlikely(!rte_spinlock_is_locked(&vq->access_lock))) { + VHOST_LOG_CONFIG(ERR, "(%s) %s() called without access lock taken.\n", + dev->ifname, __func__); + return -1; + } + if (!vq->async) return 0; @@ -1957,6 +1969,12 @@ rte_vhost_async_get_inflight_thread_unsafe(int vid, uint16_t queue_id) if (vq == NULL) return ret; + if (unlikely(!rte_spinlock_is_locked(&vq->access_lock))) { + VHOST_LOG_CONFIG(ERR, "(%s) %s() called without access lock taken.\n", + dev->ifname, __func__); + return -1; + } + if (!vq->async) return ret; diff --git a/lib/vhost/virtio_net.c b/lib/vhost/virtio_net.c index c8905c770a..4961d39007 100644 --- a/lib/vhost/virtio_net.c +++ b/lib/vhost/virtio_net.c @@ -2144,6 +2144,12 @@ rte_vhost_clear_queue_thread_unsafe(int vid, uint16_t queue_id, vq = dev->virtqueue[queue_id]; + if (unlikely(!rte_spinlock_is_locked(&vq->access_lock))) { + VHOST_LOG_DATA(ERR, "(%s) %s() called without access lock taken.\n", + dev->ifname, __func__); + return -1; + } + if (unlikely(!vq->async)) { VHOST_LOG_DATA(ERR, "(%s) %s: async not registered for queue id %d.\n", dev->ifname, __func__, queue_id); -- 2.39.5