Linux Sound subsystem development
 help / color / mirror / Atom feed
From: Takashi Iwai <tiwai@suse.de>
To: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Cc: Junrui Luo <moonafterrain@outlook.com>,
	Takashi Iwai <tiwai@suse.de>,
	linux-sound@vger.kernel.org, Yuhao Jiang <danisjiang@gmail.com>
Subject: Re: [PATCH v2] ALSA: firewire-motu: fix buffer overflow in hwdep read for DSP events
Date: Sun, 14 Dec 2025 08:52:32 +0100	[thread overview]
Message-ID: <87fr9d8pq7.wl-tiwai@suse.de> (raw)
In-Reply-To: <20251214015741.GA665386@workstation.local>

On Sun, 14 Dec 2025 02:57:41 +0100,
Takashi Sakamoto wrote:
> 
> Hi,
> 
> Sorry for my late reply, but I always postpone my review work during the
> merge window.
> 
> On Mon, Dec 08, 2025 at 08:09:09PM +0800, Junrui Luo wrote:
> > The DSP event handling code in hwdep_read() could write more bytes to
> > the user buffer than requested, when a user provides a buffer smaller
> > than the event header size (8 bytes).
> > 
> > In the put_user() loop that copies event data, when the user buffer
> > size is not aligned to 4 bytes, it could overwrite beyond the buffer
> > boundary.
> > 
> > Fix by:
> > - using min_t() to clamp the copy size
> > - Adding a bounds check before put_user()
> > 
> > This ensures we never write more than the user requested.
> > 
> > Fixes: 634ec0b2906e ("ALSA: firewire-motu: notify event for parameter change in register DSP model")
> > Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
> > ---
> > Changes in v2:
> > - Also fix the similar issue in the put_user() loop suggested by Takashi Iwai
> > - Link to v1: https://lore.kernel.org/all/SYBPR01MB78810656377E79E58350D951AFD9A@SYBPR01MB7881.ausprd01.prod.outlook.com/T/#u
> > ---
> >  sound/firewire/motu/motu-hwdep.c | 7 ++++---
> >  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> Indeed, I admit my below lines are enough rough. Thanks for your correction.
> 
> > diff --git a/sound/firewire/motu/motu-hwdep.c b/sound/firewire/motu/motu-hwdep.c
> > index 981c19430cb0..89dc436a0652 100644
> > --- a/sound/firewire/motu/motu-hwdep.c
> > +++ b/sound/firewire/motu/motu-hwdep.c
> > @@ -75,7 +75,7 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
> >  		while (consumed < count &&
> >  		       snd_motu_register_dsp_message_parser_copy_event(motu, &ev)) {
> >  			ptr = (u32 __user *)(buf + consumed);
> > -			if (put_user(ev, ptr))
> > +			if (consumed + sizeof(ev) > count || put_user(ev, ptr))
> >  				return -EFAULT;
> 
> I think it is too strong when there is no rest to store the event data
> after filling some events on the given buffer. Let us move the size
> check to the loop condition? Like:
> 
> ```
> while (consumed + sizeof(ev) < count &&
>    snd_motu_register_dsp_message_parser_copy_event(motu, &ev)) {
>     u32 __user *ptr = (u32 __user *)(buf + consumed);
> 
>     if (put_user(ev, ptr))
>         return -EFAULT;
> 
>     consumed += sizeof(ev);
> }
> ```
> 
> We can guarantee the space for one event at least in every iteration of
> loop.
> 
> >  			consumed += sizeof(ev);
> >  		}
> > @@ -83,10 +83,11 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
> >  		event.motu_register_dsp_change.type = SNDRV_FIREWIRE_EVENT_MOTU_REGISTER_DSP_CHANGE;
> >  		event.motu_register_dsp_change.count =
> >  			(consumed - sizeof(event.motu_register_dsp_change)) / 4;
> > -		if (copy_to_user(buf, &event, sizeof(event.motu_register_dsp_change)))
> > +		if (copy_to_user(buf, &event,
> > +				 min_t(long, count, sizeof(event.motu_register_dsp_change))))
> >  			return -EFAULT;
> >  
> > -		count = consumed;
> > +		count = min_t(long, count, consumed);
> >  	} else {
> >  		spin_unlock_irq(&motu->lock);
> 
> In my opinion, if there is no space for data header, the overall copying
> should be canceled in advance, thus:
> 
> ```
> } else if (has_dsp_event(motu)) {
>     size_t consumed = 0;
>     u32 ev;
> 
>     spin_unlock_irq(&motu->lock);
> 
>     if (count < sizeof(event.motu_register_dsp_change))
>             return 0;
> 
>     // Header is filled later.
>     consumed += sizeof(event.motu_register_dsp_change);
>     ...
> ```
> 
> (In the case of failure to access to userspace for the data header, the
> underlying layer for register DSP event should have peek/ack mechanism,
> however I'm too lazy...)

It's a question of API design, after all.  If the size shortage
shouldn't be  treated as an error, it can be as your suggestion.
Feel free to submit the change :)


thanks,

Takashi

      reply	other threads:[~2025-12-14  7:52 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-12-08 12:09 [PATCH v2] ALSA: firewire-motu: fix buffer overflow in hwdep read for DSP events Junrui Luo
2025-12-08 12:12 ` Takashi Iwai
2025-12-14  1:57 ` Takashi Sakamoto
2025-12-14  7:52   ` Takashi Iwai [this message]

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=87fr9d8pq7.wl-tiwai@suse.de \
    --to=tiwai@suse.de \
    --cc=danisjiang@gmail.com \
    --cc=linux-sound@vger.kernel.org \
    --cc=moonafterrain@outlook.com \
    --cc=o-takashi@sakamocchi.jp \
    /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