Linux USB
 help / color / mirror / Atom feed
* [PATCH v2] usb: gadget: f_uac1_legacy: fix use-after-free in gaudio_open_snd_dev()
@ 2026-05-25  4:33 Adrian Korwel
  2026-05-25  5:56 ` Greg KH
  0 siblings, 1 reply; 22+ messages in thread
From: Adrian Korwel @ 2026-05-25  4:33 UTC (permalink / raw)
  To: linux-usb; +Cc: gregkh, stable

Three bugs exist in this driver related to ALSA device file lifetime:

1. gaudio_open_snd_dev() opens the ALSA control file first, then the
   PCM playback file. If filp_open() for playback fails, the function
   returns without closing the already-opened control file handle.

2. playback_default_hw_params() return value was ignored. If it fails,
   both the control and playback file handles are leaked, causing
   gaudio_cleanup() to call filp_close() on already-freed file objects.

3. f_audio_bind() guards gaudio_setup() with an 'audio_opts->bound'
   flag to prevent re-initialization, but the fail: error path
   unconditionally calls gaudio_cleanup(). On repeated bind attempts
   after failure, this closes file handles that were opened in a
   previous bind invocation and already freed by RCU, causing a
   use-after-free detected by KASAN:

   BUG: KASAN: slab-use-after-free in filp_flush+0x23/0x1b0
   Read of size 8 at addr ffff88810d5523a8 by task bash/306
   ...
   gaudio_cleanup+0x59/0x100
   f_audio_bind+0x4b0/0x590

Fix all three issues:
- Close already-opened file handles on each error path in
  gaudio_open_snd_dev().
- Check and propagate the return value of playback_default_hw_params().
- Remove the 'bound' guard and call gaudio_setup() unconditionally in
  f_audio_bind(), making setup and cleanup a matched pair within each
  bind invocation. Remove the now-unused 'bound' field from the opts
  struct.

Additionally, f_audio_disable() was an empty stub. Add
cancel_work_sync() to ensure the playback work item is not in flight
when the function is unbound and the audio struct is freed.

Changes since v1:
- Added removal of the 'bound' guard in f_audio_bind() which was the
  root cause of the repeated-bind UAF
- Added cancel_work_sync() to f_audio_disable()
- Removed now-unused 'bound' field from struct f_uac1_legacy_opts

Fixes: d355339eecd9 ("usb: gadget: function: make current f_uac1
implementation legacy")
Cc: stable@vger.kernel.org
Signed-off-by: Adrian Korwel <adriank20047@gmail.com>
---
 drivers/usb/gadget/function/f_uac1_legacy.c | 15 +++++++--------
 drivers/usb/gadget/function/u_uac1_legacy.c | 10 +++++++++-
 drivers/usb/gadget/function/u_uac1_legacy.h |  1 -
 3 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/gadget/function/f_uac1_legacy.c
b/drivers/usb/gadget/function/f_uac1_legacy.c
index 5d201a2e30e7..798fbb8550bc 100644
--- a/drivers/usb/gadget/function/f_uac1_legacy.c
+++ b/drivers/usb/gadget/function/f_uac1_legacy.c
@@ -697,7 +697,9 @@ static int f_audio_get_alt(struct usb_function *f,
unsigned intf)

 static void f_audio_disable(struct usb_function *f)
 {
-       return;
+       struct f_audio *audio = func_to_audio(f);
+
+       cancel_work_sync(&audio->playback_work);
 }

 /*-------------------------------------------------------------------------*/
@@ -735,13 +737,10 @@ f_audio_bind(struct usb_configuration *c, struct
usb_function *f)

        audio_opts = container_of(f->fi, struct f_uac1_legacy_opts, func_inst);
        audio->card.gadget = c->cdev->gadget;
-       /* set up ASLA audio devices */
-       if (!audio_opts->bound) {
-               status = gaudio_setup(&audio->card);
-               if (status < 0)
-                       return status;
-               audio_opts->bound = true;
-       }
+       /* set up ALSA audio devices */
+       status = gaudio_setup(&audio->card);
+       if (status < 0)
+               return status;
        us = usb_gstrings_attach(cdev, uac1_strings, ARRAY_SIZE(strings_uac1));
        if (IS_ERR(us))
                return PTR_ERR(us);
diff --git a/drivers/usb/gadget/function/u_uac1_legacy.c
b/drivers/usb/gadget/function/u_uac1_legacy.c
index 01016102fa17..5bcd3afd6366 100644
--- a/drivers/usb/gadget/function/u_uac1_legacy.c
+++ b/drivers/usb/gadget/function/u_uac1_legacy.c
@@ -226,12 +226,20 @@ static int gaudio_open_snd_dev(struct gaudio *card)

                ERROR(card, "No such PCM playback device: %s\n", fn_play);
                snd->filp = NULL;
+               filp_close(card->control.filp, NULL);
+               card->control.filp = NULL;
                return ret;
        }
        pcm_file = snd->filp->private_data;
        snd->substream = pcm_file->substream;
        snd->card = card;
-       playback_default_hw_params(snd);
+       if (playback_default_hw_params(snd) < 0) {
+               filp_close(snd->filp, NULL);
+               snd->filp = NULL;
+               filp_close(card->control.filp, NULL);
+               card->control.filp = NULL;
+               return -EINVAL;
+       }

        /* Open PCM capture device and setup substream */
        snd = &card->capture;
diff --git a/drivers/usb/gadget/function/u_uac1_legacy.h
b/drivers/usb/gadget/function/u_uac1_legacy.h
index b5df9bcbbeba..fd22fd37fe53 100644
--- a/drivers/usb/gadget/function/u_uac1_legacy.h
+++ b/drivers/usb/gadget/function/u_uac1_legacy.h
@@ -61,7 +61,6 @@ struct f_uac1_legacy_opts {
        char                            *fn_play;
        char                            *fn_cap;
        char                            *fn_cntl;
-       unsigned                        bound:1;
        unsigned                        fn_play_alloc:1;
        unsigned                        fn_cap_alloc:1;
        unsigned                        fn_cntl_alloc:1;
-- 
2.43.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2026-06-25 14:01 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-25  4:33 [PATCH v2] usb: gadget: f_uac1_legacy: fix use-after-free in gaudio_open_snd_dev() Adrian Korwel
2026-05-25  5:56 ` Greg KH
2026-05-25 14:30   ` Adrian Korwel
2026-05-25 14:33     ` Adrian Korwel
2026-06-25 13:57       ` Greg KH
2026-05-25 14:34     ` Adrian Korwel
2026-05-25 14:36     ` Adrian Korwel
2026-05-25 14:37     ` Adrian Korwel
2026-05-25 19:08       ` Greg KH
2026-05-25 20:24         ` [PATCH 1/4] USB: serial: io_ti: fix heap overflow in build_i2c_fw_hdr() Adrian Korwel
2026-05-25 20:24           ` [PATCH 1/4] usb: gadget: f_uac1_legacy: fix file handle leaks in gaudio_open_snd_dev() Adrian Korwel
2026-05-25 20:24           ` [PATCH 2/4] " Adrian Korwel
2026-05-25 20:24           ` [PATCH 2/4] usb: gadget: f_uac1_legacy: fix use-after-free caused by bound guard Adrian Korwel
2026-05-25 20:24           ` [PATCH 3/4] usb: gadget: f_uac1_legacy: cancel work in f_audio_disable() Adrian Korwel
2026-05-25 20:24           ` [PATCH 3/4] usb: gadget: f_uac1_legacy: fix use-after-free caused by bound guard Adrian Korwel
2026-05-25 20:24           ` [PATCH 4/4] usb: gadget: f_uac1_legacy: cancel work in f_audio_disable() Adrian Korwel
2026-05-25 20:24           ` [PATCH 4/4] usb: typec: thunderbolt: cancel work before altmode is removed Adrian Korwel
2026-05-25 20:26         ` [PATCH 1/4] usb: gadget: f_uac1_legacy: fix file handle leaks in gaudio_open_snd_dev() Adrian Korwel
2026-05-25 20:26           ` [PATCH 2/4] usb: gadget: f_uac1_legacy: fix use-after-free caused by bound guard Adrian Korwel
2026-05-25 20:26           ` [PATCH 3/4] usb: gadget: f_uac1_legacy: cancel work in f_audio_disable() Adrian Korwel
2026-05-25 20:26           ` [PATCH 4/4] usb: typec: thunderbolt: cancel work before altmode is removed Adrian Korwel
2026-06-25 14:00           ` [PATCH 1/4] usb: gadget: f_uac1_legacy: fix file handle leaks in gaudio_open_snd_dev() Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox