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:
