Linux Sound subsystem development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Sinan Turunc" <enscrpt@pm.me>
Cc: linux-sound@vger.kernel.org
Subject: Re: [PATCH v3 2/2] ALSA: usx2y: Guard the playback copy
Date: Wed, 04 Nov 2026 11:02:48 +0000	[thread overview]
Message-ID: <sashiko-outbox-197138@kernel.org> (raw)
In-Reply-To: <20261104105228.1124-3-enscrpt@pm.me>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] ALSA: usx2y: incomplete packet length validation in usx2y_urb_play_prepare()
--

commit 8f4cd6a52f3d49a81dfc6755062eeb7276e1ee4b
Author: Sinan Turunc <enscrpt@pm.me>

ALSA: usx2y: Guard the playback copy

This commit adds bounds checks in usx2y_urb_play_prepare() to verify that each
packet fits within the playback endpoint's maxpacksize and that the total URB
frame count does not exceed the ring buffer size, returning -EPIPE on a
violation.

> diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
> index ee224b4dfb046..5f241d454012f 100644
> --- a/sound/usb/usx2y/usbusx2yaudio.c
> +++ b/sound/usb/usx2y/usbusx2yaudio.c
> @@ -112,7 +112,8 @@ static int usx2y_urb_play_prepare(struct snd_usx2y_substream *subs,
>  		/* calculate the size of a packet */
>  		counts = cap_urb->iso_frame_desc[pack].actual_length / usx2y->stride;
>  		count += counts;
> -		if (counts < 43 || counts > 50) {
> +		if (counts < 43 || counts > 50 ||
> +		    counts * usx2y->stride > subs->maxpacksize) {
>  			dev_err(&usx2y->dev->dev, "%s: should not be here with counts=%i\n",
>  				__func__, counts);
>  			return -EPIPE;
> @@ -125,6 +126,16 @@ static int usx2y_urb_play_prepare(struct snd_usx2y_substream *subs,
>  		urb->iso_frame_desc[pack].length = cap_urb->iso_frame_desc[pack].actual_length;

[Severity: High]
What happens in usx2y_urb_play_prepare() in sound/usb/usx2y/usbusx2yaudio.c
when i_usx2y_urb_complete() -> usx2y_usbframe_complete() ->
usx2y_urb_play_prepare() -> usx2y_urb_submit() processes a capture URB whose
cap_urb->iso_frame_desc[pack].actual_length is not a multiple of
usx2y->stride?

Because counts is computed via truncating integer division:

	counts = cap_urb->iso_frame_desc[pack].actual_length / usx2y->stride;

any remainder actual_length % usx2y->stride is discarded from counts, and the
new guard only checks the truncated byte count counts * usx2y->stride against
subs->maxpacksize. However, the playback ISO descriptor offsets and lengths
are still populated from the untruncated actual_length:

	urb->iso_frame_desc[pack].offset = pack ?
		urb->iso_frame_desc[pack - 1].offset +
		urb->iso_frame_desc[pack - 1].length :
		0;
	urb->iso_frame_desc[pack].length = cap_urb->iso_frame_desc[pack].actual_length;

Meanwhile, the ring-buffer wrap check, the memcpy() into subs->tmpbuf, the
non-wrapping pointer slice into runtime->dma_area, and
urb->transfer_buffer_length all account for only count * usx2y->stride bytes:

		} else {
			/* set the buffer pointer */
			urb->transfer_buffer = runtime->dma_area + subs->hwptr * usx2y->stride;
			subs->hwptr += count;
			if (subs->hwptr >= runtime->buffer_size)
				subs->hwptr -= runtime->buffer_size;
		}
	} else {
		urb->transfer_buffer = subs->tmpbuf;
	}
	urb->transfer_buffer_length = count * usx2y->stride;

If actual_length has a non-zero remainder modulo usx2y->stride, can this still
read past the end of subs->tmpbuf or runtime->dma_area? For example:

1. When counts * usx2y->stride == subs->maxpacksize and actual_length has
   trailing remainder bytes (such as stride = 4, subs->maxpacksize = 200, and
   actual_length = 203, giving counts = 50), counts * usx2y->stride >
   subs->maxpacksize does not trigger, so urb->iso_frame_desc[pack].length
   (203) exceeds subs->maxpacksize (200) and the cumulative ISO descriptors
   across nr_of_packs() packets exceed the subs->tmpbuf allocation of
   nr_of_packs() * subs->maxpacksize.

2. Even when actual_length <= subs->maxpacksize (such as stride = 4,
   subs->maxpacksize = 200, and actual_length = 195, giving counts = 48 and
   counts * stride = 192), the ISO descriptors in urb->iso_frame_desc[] span
   more bytes than urb->transfer_buffer_length. When subs->hwptr + count ==
   runtime->buffer_size in the non-wrapping branch, only count * usx2y->stride
   bytes remain before the end of runtime->dma_area, so the ISO descriptors
   extend past the end of runtime->dma_area.

Should usx2y_urb_play_prepare() either size urb->iso_frame_desc[pack].length
as counts * usx2y->stride or reject packets where actual_length is not aligned
to usx2y->stride?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261104105228.1124-1-enscrpt@pm.me?part=2

  reply	other threads:[~2026-11-04 11:02 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-04 10:52 [PATCH v3 0/2] ALSA: usx2y: Bound the PCM buffer by the URB size Sinan Turunc
2026-11-04 10:52 ` [PATCH v3 1/2] ALSA: usx2y: Require a buffer of two URBs Sinan Turunc
2026-11-04 10:52 ` [PATCH v3 2/2] ALSA: usx2y: Guard the playback copy Sinan Turunc
2026-11-04 11:02   ` sashiko-bot [this message]
2026-11-04 12:21     ` Sinan Turunc

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-197138@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=enscrpt@pm.me \
    --cc=linux-sound@vger.kernel.org \
    --cc=sashiko-reviews@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox