This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 0b8c14ffdc81642f228d35f38a44e0a17de2d42f
Author: jinxiuxu <[email protected]>
AuthorDate: Wed May 21 15:19:18 2025 +0800

    drivers/virtio-snd: protect cache_buffers with the driver lock
    
    cache_buffers is changed by virtio_snd_send_pcm() and the pcm notify
    callback and read by AUDIOIOC_GETLATENCY, possibly on different CPUs,
    and the increment ran after the lock was dropped.  Hold priv->lock
    around all three accesses.
    
    Signed-off-by: jinxiuxu <[email protected]>
---
 drivers/virtio/virtio-snd.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/virtio/virtio-snd.c b/drivers/virtio/virtio-snd.c
index c7cb8b9387c..165dba9abdf 100644
--- a/drivers/virtio/virtio-snd.c
+++ b/drivers/virtio/virtio-snd.c
@@ -338,12 +338,14 @@ virtio_snd_get_support_formats(FAR const struct 
virtio_snd_pcm_info *info,
 static void virtio_snd_pcm_notify_cb(FAR struct virtqueue *vq)
 {
   FAR struct virtio_snd_s *priv = vq->vq_dev->priv;
+  irqstate_t flags;
 
+  flags = spin_lock_irqsave(&priv->lock);
   for (; ; )
     {
       FAR struct virtio_snd_buffer_s *buf;
       FAR struct virtio_snd_dev_s *sdev;
-      buf = virtqueue_get_buffer_lock(vq, NULL, NULL, &priv->lock);
+      buf = virtqueue_get_buffer(vq, NULL, NULL);
       if (buf == NULL)
         {
           break;
@@ -365,6 +367,8 @@ static void virtio_snd_pcm_notify_cb(FAR struct virtqueue 
*vq)
                           NULL, OK);
         }
     }
+
+  spin_unlock_irqrestore(&priv->lock, flags);
 }
 
 /****************************************************************************
@@ -422,8 +426,8 @@ static int virtio_snd_send_pcm(FAR struct virtio_snd_dev_s 
*sdev,
     }
 
   virtqueue_kick(vq);
-  spin_unlock_irqrestore(&priv->lock, flags);
   sdev->cache_buffers++;
+  spin_unlock_irqrestore(&priv->lock, flags);
 
   return OK;
 }
@@ -1006,8 +1010,10 @@ static int virtio_snd_ioctl(FAR struct audio_lowerhalf_s 
*dev,
                             unsigned long arg)
 {
   FAR struct virtio_snd_dev_s *sdev = (FAR struct virtio_snd_dev_s *)dev;
+  FAR struct virtio_snd_s *priv = sdev->priv;
   FAR struct ap_buffer_info_s *bufinfo;
   FAR long *latency = (FAR long *)arg;
+  irqstate_t flags;
 
   switch (cmd)
     {
@@ -1018,8 +1024,10 @@ static int virtio_snd_ioctl(FAR struct audio_lowerhalf_s 
*dev,
         break;
 
       case AUDIOIOC_GETLATENCY:
+        flags = spin_lock_irqsave(&priv->lock);
         *latency = sdev->cache_buffers * sdev->period_bytes /
                    sdev->frame_size;
+        spin_unlock_irqrestore(&priv->lock, flags);
         break;
 
       default:

Reply via email to