From: sashiko-bot@kernel.org
To: "Joonho Lee" <mynameisjune111@gmail.com>, linux-sound@vger.kernel.org
Cc: virtualization@lists.linux.dev,
"Michael S. Tsirkin" <mst@redhat.com>,
"Eugenio Perez" <eperezma@redhat.com>
Subject: Re: [PATCH v15 07/12] ALSA: virtio: Keep PCM DMA buffers alive through device ownership
Date: Thu, 05 Nov 2026 00:35:11 +0000 [thread overview]
Message-ID: <sashiko-outbox-198363@kernel.org> (raw)
In-Reply-To: <20261105000915.15177-8-mynameisjune111@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] ALSA: virtio: unvalidated slice order in virtsnd_pcm_msg_complete()
--
commit b2a39e63df7fac644d0bf6ab9ec43939a12f17f0
Author: Joonho Lee <mynameisjune111@gmail.com>
ALSA: virtio: Keep PCM DMA buffers alive through device ownership
This commit retains references to the pages backing ALSA vmalloc buffers
(or uses driver-owned buffers on NOMMU systems) until queued I/O messages
are freed, and adds validation for PCM buffer bounds, period sizes, and
capture completion status and payload lengths.
> diff --git a/sound/virtio/virtio_pcm_msg.c b/sound/virtio/virtio_pcm_msg.c
> index 59ad99e21e899..9fb966a02d923 100644
> --- a/sound/virtio/virtio_pcm_msg.c
> +++ b/sound/virtio/virtio_pcm_msg.c
[ ... ]
> @@ -356,42 +540,80 @@ static void virtsnd_pcm_msg_complete(struct virtio_pcm_msg *msg,
> size_t written_bytes)
> {
> struct virtio_pcm_substream *vss = msg->substream;
> + bool capture_invalid = false;
>
> /*
> - * hw_ptr always indicates the buffer position of the first I/O message
> - * in the virtqueue. Therefore, on each completion of an I/O message,
> - * the hw_ptr value is unconditionally advanced.
> + * Completed requests can return captured data after STOP while the PCM
> + * buffer remains prepared. Once preparation ends, completions only retire
> + * queue ownership.
> */
> guard(spinlock)(&vss->lock);
> - /*
> - * If the capture substream returned an incorrect status, then just
> - * increase the hw_ptr by the message size.
> - */
> - if (vss->direction == SNDRV_PCM_STREAM_PLAYBACK ||
> - written_bytes <= sizeof(msg->status))
> - vss->hw_ptr += msg->length;
> - else
> - vss->hw_ptr += written_bytes - sizeof(msg->status);
> + if (vss->direction == SNDRV_PCM_STREAM_CAPTURE &&
> + (!vss->prepared ||
> + (vss->stopped && written_bytes <= sizeof(msg->status)))) {
> + msg->length = 0;
> + vss->msg_count--;
> + if (!vss->msg_count)
> + wake_up_all(&vss->msg_empty);
> + return;
> + }
>
> - if (vss->hw_ptr >= vss->buffer_bytes)
> - vss->hw_ptr -= vss->buffer_bytes;
> + /* A non-staged capture request must return its full payload. */
> + if (vss->direction == SNDRV_PCM_STREAM_CAPTURE &&
> + (written_bytes < sizeof(msg->status) ||
> + le32_to_cpu(msg->status.status) != VIRTIO_SND_S_OK ||
> + written_bytes - sizeof(msg->status) != msg->length)) {
> + dev_err_ratelimited(&vss->snd->vdev->dev,
> + "SID %u: invalid capture status or length\n",
> + vss->sid);
> + vss->xfer_xrun = true;
> + capture_invalid = true;
> + }
> +#ifndef CONFIG_MMU
> + if (vss->direction == SNDRV_PCM_STREAM_CAPTURE &&
> + vss->prepared && !capture_invalid &&
> + written_bytes > sizeof(msg->status)) {
> + struct snd_pcm_runtime *runtime =
> + vss->substream ? vss->substream->runtime : NULL;
> +
> + if (!runtime || !runtime->dma_area || !vss->owned_dma_area ||
> + msg->data_offset > runtime->dma_bytes ||
> + msg->length > runtime->dma_bytes - msg->data_offset ||
> + msg->data_offset > vss->owned_dma_bytes ||
> + msg->length > vss->owned_dma_bytes - msg->data_offset) {
> + dev_err_ratelimited(&vss->snd->vdev->dev,
> + "SID %u: invalid capture buffer for I/O message\n",
> + vss->sid);
> + vss->xfer_xrun = true;
> + capture_invalid = true;
> + } else {
> + memcpy(runtime->dma_area + msg->data_offset,
> + vss->owned_dma_area + msg->data_offset, msg->length);
> + }
> + }
> +#endif
> + /* Publish pointer progress only for a complete TX or valid RX request. */
> + if (!capture_invalid) {
> + vss->hw_ptr += msg->length;
> + if (vss->hw_ptr >= vss->buffer_bytes)
> + vss->hw_ptr -= vss->buffer_bytes;
> + }
[Severity: Medium]
Can virtsnd_pcm_msg_complete() expose unwritten ring buffer slices to
userspace if capture descriptors complete out of order or after an earlier
descriptor is retired without advancing vss->hw_ptr?
In ordinary capture mode, each descriptor vss->msgs[i] targets a fixed
ring buffer slice at offset i * period_bytes, while
virtsnd_pcm_msg_complete() advances vss->hw_ptr by msg->length without
checking that the completing msg corresponds to the slice at vss->hw_ptr.
When vss->stopped is true while vss->prepared remains true (such as after
SNDRV_PCM_TRIGGER_STOP), if vss->msgs[0] (slice 0) completes empty with
written_bytes <= sizeof(msg->status), virtsnd_pcm_msg_complete() retires
vss->msgs[0] and returns early without advancing vss->hw_ptr or latching
vss->xfer_xrun.
If vss->msgs[1] (slice 1, at offset period_bytes) subsequently completes
with a full period, or if the device completes vss->msgs[1] before
vss->msgs[0] out of order, virtsnd_pcm_msg_complete() writes or copies the
payload into slice 1 at offset period_bytes and advances vss->hw_ptr from
0 to period_bytes. Subsequent calls to virtsnd_pcm_pointer() and
virtsnd_pcm_ack() see vss->xfer_xrun == false and publish slice 0, which
was never filled by vss->msgs[0], as readable captured audio.
Similarly, if an earlier capture descriptor failed validation and set
vss->xfer_xrun = true without advancing vss->hw_ptr, a later valid
descriptor completion still copies NOMMU data into its own offset and
advances vss->hw_ptr because virtsnd_pcm_msg_complete() only checks the
local capture_invalid flag rather than vss->xfer_xrun.
Should virtsnd_pcm_msg_complete() verify that the completing message matches
the expected ring slice at vss->hw_ptr and avoid advancing vss->hw_ptr (or
accepting further completions) once an empty stopped descriptor has been
retired or vss->xfer_xrun has been latched?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261105000915.15177-1-mynameisjune111@gmail.com?part=7
next prev parent reply other threads:[~2026-11-05 0:35 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-05 0:09 [PATCH v15 00/12] ALSA: virtio: staged capture recovery and PCM ACK handoff Joonho Lee
2026-11-05 0:09 ` [PATCH v15 01/12] ALSA: pcm: mark stop-threshold accesses for capture policy sampling Joonho Lee
2026-11-05 0:13 ` sashiko-bot
2026-11-05 0:09 ` [PATCH v15 02/12] ALSA: pcm: report partial progress under the stream lock Joonho Lee
2026-11-05 0:13 ` sashiko-bot
2026-11-05 0:09 ` [PATCH v15 03/12] ALSA: pcm: add an optional reset operation " Joonho Lee
2026-11-05 0:15 ` sashiko-bot
2026-11-05 0:09 ` [PATCH v15 04/12] ALSA: virtio: Propagate PCM send failures through ACK Joonho Lee
2026-11-05 0:35 ` sashiko-bot
2026-11-05 0:09 ` [PATCH v15 05/12] ALSA: virtio: Recover PCM state after a failed start Joonho Lee
2026-11-05 0:34 ` sashiko-bot
2026-11-05 0:09 ` [PATCH v15 06/12] ALSA: virtio: Retain queued messages through device reset Joonho Lee
2026-11-05 0:30 ` sashiko-bot
2026-11-05 0:09 ` [PATCH v15 07/12] ALSA: virtio: Keep PCM DMA buffers alive through device ownership Joonho Lee
2026-11-05 0:35 ` sashiko-bot [this message]
2026-11-05 0:09 ` [PATCH v15 08/12] ALSA: virtio: Keep control payloads alive through DMA completion Joonho Lee
2026-11-05 0:17 ` sashiko-bot
2026-11-05 0:09 ` [PATCH v15 09/12] ALSA: virtio: wait through signals for PCM teardown Joonho Lee
2026-11-05 0:27 ` sashiko-bot
2026-11-05 0:09 ` [PATCH v15 10/12] ALSA: virtio: add staged capture and serialize PCM lifecycle accounting Joonho Lee
2026-11-05 0:44 ` sashiko-bot
2026-11-05 0:09 ` [PATCH v15 11/12] ALSA: virtio: prioritize staged capture period work Joonho Lee
2026-11-05 0:21 ` sashiko-bot
2026-11-05 0:09 ` [PATCH v15 12/12] docs: describe virtio-sound capture options Joonho Lee
2026-11-05 0:17 ` sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-198363@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=eperezma@redhat.com \
--cc=linux-sound@vger.kernel.org \
--cc=mst@redhat.com \
--cc=mynameisjune111@gmail.com \
--cc=sashiko-reviews@lists.linux.dev \
--cc=virtualization@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.