Re: [syzbot] [sound?] [usb?] general protection fault in snd_usbmidi_do_output

Takashi Iwai
2025-09-27T16:07:57Z

On Sat, 27 Sep 2025 17:41:09 +0200,
Jeongjun Park wrote:
>
> Hi,
>
> Takashi Iwai <tiwai@suse.de> wrote:
> >
> > On Sat, 27 Sep 2025 12:36:07 +0200,
> > Jeongjun Park wrote:
> > >
> > > syzbot <syzbot+f02665daa2abeef4a947@syzkaller.appspotmail.com> wrote:
> > > >
> > > > Hello,
> > > >
> > > > syzbot has tested the proposed patch but the reproducer is still triggering an issue:
> > > > KASAN: slab-use-after-free Write in snd_usbmidi_in_urb_complete
> > > >
> > > > ==================================================================
> > > > BUG: KASAN: slab-use-after-free in snd_usbmidi_in_urb_complete+0x389/0x3c0 sound/usb/midi.c:251
> > > > Write of size 1 at addr ffff888074717943 by task kworker/1:3/5866
> > > >
> > >
> > > Wow, the UAF bug still occurs?
> > >
> > > But... this UAF seems to be a problem with how midi handles urb rather
> > > than a problem with my patch.
> > >
> > > Is there something wrong with the way snd_usbmidi_in_urb_complete() is
> > > implemented?
> >
> > This can be rather a missing kill-and-cleanup in the code path.
> > So the patch like below.
> >
> > Could you check whether this works for you instead of your fix, too?
> > timer_shutdown_sync() is already called in snd_usbmidi_disconnect(),
> > and the call in snd_usbmidi_free() should be superfluous after this
> > change.
> >
>
> Since both my tests and syzbot tests did not cause any bugs when applying
> this patch, I think the root cause of this vulnerability is the missing
> kill error_timer + urb.
>
> So, I think it would be okay to patch it this way, but in addition, since
> most of the endpoint delete-related code that existed in
> snd_usbmidi_free() is now done in snd_usbmidi_disconnect(),
> I think it would be appropriate to modify it to only perform
> kfree(ep->out) as in this patch below.

Yes, it makes sense.

thanks,

Takashi

> ---
> sound/usb/midi.c | 9 ++++-----
> 1 file changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/sound/usb/midi.c b/sound/usb/midi.c
> index acb3bf92857c..97e7e7662b12 100644
> --- a/sound/usb/midi.c
> +++ b/sound/usb/midi.c
> @@ -1522,15 +1522,14 @@ static void snd_usbmidi_free(struct snd_usb_midi *umidi)
> {
> int i;
>
> + if (!umidi->disconnected)
> + snd_usbmidi_disconnect(&umidi->list);
> +
> for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
> struct snd_usb_midi_endpoint *ep = &umidi->endpoints[i];
> - if (ep->out)
> - snd_usbmidi_out_endpoint_delete(ep->out);
> - if (ep->in)
> - snd_usbmidi_in_endpoint_delete(ep->in);
> + kfree(ep->out);
> }
> mutex_destroy(&umidi->mutex);
> - timer_shutdown_sync(&umidi->error_timer);
> kfree(umidi);
> }
>
> --
>
> >
> > thanks,
> >
> > Takashi
> >
> > --- a/sound/usb/midi.c
> > +++ b/sound/usb/midi.c
> > @@ -1522,6 +1522,9 @@ static void snd_usbmidi_free(struct snd_usb_midi *umidi)
> > {
> > int i;
> >
> > + if (!umidi->disconnected)
> > + snd_usbmidi_disconnect(&umidi->list);
> > +
> > for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
> > struct snd_usb_midi_endpoint *ep = &umidi->endpoints[i];
> > if (ep->out)
>
> Regards,
> Jeongjun Park