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; 20+ 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] 20+ messages in thread

* Re: [PATCH v2] usb: gadget: f_uac1_legacy: fix use-after-free in gaudio_open_snd_dev()
  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
  0 siblings, 1 reply; 20+ messages in thread
From: Greg KH @ 2026-05-25  5:56 UTC (permalink / raw)
  To: Adrian Korwel; +Cc: linux-usb, stable

On Sun, May 24, 2026 at 11:33:21PM -0500, Adrian Korwel wrote:
> 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.

Why is this not broken up into smaller patches to corrispond with each
issue/fix?  Please do so.


> 
> 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

The "changes" go below the --- line, right?

thanks,

greg k-h

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

* Re: [PATCH v2] usb: gadget: f_uac1_legacy: fix use-after-free in gaudio_open_snd_dev()
  2026-05-25  5:56 ` Greg KH
@ 2026-05-25 14:30   ` Adrian Korwel
  2026-05-25 14:33     ` Adrian Korwel
                       ` (3 more replies)
  0 siblings, 4 replies; 20+ messages in thread
From: Adrian Korwel @ 2026-05-25 14:30 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-usb, stable

On Mon, May 26, 2026 at 12:57AM, Greg KH wrote:
> Why is this not broken up into smaller patches...
> The "changes" go below the --- line, right?

Apologies for the formatting issues. Please find v3 below as a series
of 4 patches. Fixes split into separate patches and changelog moved
below the --- line.

Adrian Korwel (4):
  usb: gadget: f_uac1_legacy: fix file handle leaks in gaudio_open_snd_dev()
  usb: gadget: f_uac1_legacy: fix use-after-free caused by bound guard
  usb: gadget: f_uac1_legacy: cancel work in f_audio_disable()
  usb: typec: thunderbolt: cancel work before altmode is removed

 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 -
 drivers/usb/typec/altmodes/thunderbolt.c    |  2 ++
 4 files changed, 18 insertions(+), 10 deletions(-)

On Mon, May 25, 2026 at 12:57 AM Greg KH <gregkh@linuxfoundation.org> wrote:
>
> On Sun, May 24, 2026 at 11:33:21PM -0500, Adrian Korwel wrote:
> > 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.
>
> Why is this not broken up into smaller patches to corrispond with each
> issue/fix?  Please do so.
>
>
> >
> > 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
>
> The "changes" go below the --- line, right?
>
> thanks,
>
> greg k-h

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

* Re: [PATCH v2] usb: gadget: f_uac1_legacy: fix use-after-free in gaudio_open_snd_dev()
  2026-05-25 14:30   ` Adrian Korwel
@ 2026-05-25 14:33     ` Adrian Korwel
  2026-05-25 14:34     ` Adrian Korwel
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 20+ messages in thread
From: Adrian Korwel @ 2026-05-25 14:33 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-usb, stable

[PATCH v3 1/4] usb: gadget: f_uac1_legacy: fix file handle leaks in
gaudio_open_snd_dev()

gaudio_open_snd_dev() opens the ALSA control device file first, then
opens the PCM playback device. On two error paths the control file
handle is leaked:

When filp_open() for the playback device fails, the function returns
immediately without closing the already-opened control file handle.

When playback_default_hw_params() fails, its return value was ignored
and both the playback and control file handles were leaked.

Both leaks result in gaudio_cleanup() calling filp_close() on already
freed file objects, causing a use-after-free.

Fix by closing previously opened file handles before returning on
each error path, and by checking the return value of
playback_default_hw_params().

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/u_uac1_legacy.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

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;
-- 
2.43.0

On Mon, May 25, 2026 at 9:30 AM Adrian Korwel <adriank20047@gmail.com> wrote:
>
> On Mon, May 26, 2026 at 12:57AM, Greg KH wrote:
> > Why is this not broken up into smaller patches...
> > The "changes" go below the --- line, right?
>
> Apologies for the formatting issues. Please find v3 below as a series
> of 4 patches. Fixes split into separate patches and changelog moved
> below the --- line.
>
> Adrian Korwel (4):
>   usb: gadget: f_uac1_legacy: fix file handle leaks in gaudio_open_snd_dev()
>   usb: gadget: f_uac1_legacy: fix use-after-free caused by bound guard
>   usb: gadget: f_uac1_legacy: cancel work in f_audio_disable()
>   usb: typec: thunderbolt: cancel work before altmode is removed
>
>  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 -
>  drivers/usb/typec/altmodes/thunderbolt.c    |  2 ++
>  4 files changed, 18 insertions(+), 10 deletions(-)
>
> On Mon, May 25, 2026 at 12:57 AM Greg KH <gregkh@linuxfoundation.org> wrote:
> >
> > On Sun, May 24, 2026 at 11:33:21PM -0500, Adrian Korwel wrote:
> > > 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.
> >
> > Why is this not broken up into smaller patches to corrispond with each
> > issue/fix?  Please do so.
> >
> >
> > >
> > > 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
> >
> > The "changes" go below the --- line, right?
> >
> > thanks,
> >
> > greg k-h

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

* Re: [PATCH v2] usb: gadget: f_uac1_legacy: fix use-after-free in gaudio_open_snd_dev()
  2026-05-25 14:30   ` Adrian Korwel
  2026-05-25 14:33     ` Adrian Korwel
@ 2026-05-25 14:34     ` Adrian Korwel
  2026-05-25 14:36     ` Adrian Korwel
  2026-05-25 14:37     ` Adrian Korwel
  3 siblings, 0 replies; 20+ messages in thread
From: Adrian Korwel @ 2026-05-25 14:34 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-usb, stable

[PATCH v3 2/4] usb: gadget: f_uac1_legacy: fix use-after-free caused
by bound guard

f_audio_bind() guards gaudio_setup() with an 'audio_opts->bound' flag
to prevent re-initialization on repeated bind attempts. However 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 by removing the bound guard and calling 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 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 | 11 ++++-------
 drivers/usb/gadget/function/u_uac1_legacy.h |  1 -
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/gadget/function/f_uac1_legacy.c
b/drivers/usb/gadget/function/f_uac1_legacy.c
index 5d201a2e30e7..6ad4b16769b7 100644
--- a/drivers/usb/gadget/function/f_uac1_legacy.c
+++ b/drivers/usb/gadget/function/f_uac1_legacy.c
@@ -735,13 +735,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.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

On Mon, May 25, 2026 at 9:30 AM Adrian Korwel <adriank20047@gmail.com> wrote:
>
> On Mon, May 26, 2026 at 12:57AM, Greg KH wrote:
> > Why is this not broken up into smaller patches...
> > The "changes" go below the --- line, right?
>
> Apologies for the formatting issues. Please find v3 below as a series
> of 4 patches. Fixes split into separate patches and changelog moved
> below the --- line.
>
> Adrian Korwel (4):
>   usb: gadget: f_uac1_legacy: fix file handle leaks in gaudio_open_snd_dev()
>   usb: gadget: f_uac1_legacy: fix use-after-free caused by bound guard
>   usb: gadget: f_uac1_legacy: cancel work in f_audio_disable()
>   usb: typec: thunderbolt: cancel work before altmode is removed
>
>  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 -
>  drivers/usb/typec/altmodes/thunderbolt.c    |  2 ++
>  4 files changed, 18 insertions(+), 10 deletions(-)
>
> On Mon, May 25, 2026 at 12:57 AM Greg KH <gregkh@linuxfoundation.org> wrote:
> >
> > On Sun, May 24, 2026 at 11:33:21PM -0500, Adrian Korwel wrote:
> > > 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.
> >
> > Why is this not broken up into smaller patches to corrispond with each
> > issue/fix?  Please do so.
> >
> >
> > >
> > > 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
> >
> > The "changes" go below the --- line, right?
> >
> > thanks,
> >
> > greg k-h

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

* Re: [PATCH v2] usb: gadget: f_uac1_legacy: fix use-after-free in gaudio_open_snd_dev()
  2026-05-25 14:30   ` Adrian Korwel
  2026-05-25 14:33     ` Adrian Korwel
  2026-05-25 14:34     ` Adrian Korwel
@ 2026-05-25 14:36     ` Adrian Korwel
  2026-05-25 14:37     ` Adrian Korwel
  3 siblings, 0 replies; 20+ messages in thread
From: Adrian Korwel @ 2026-05-25 14:36 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-usb, stable

[PATCH v3 3/4] usb: gadget: f_uac1_legacy: cancel work in f_audio_disable()

f_audio_disable() was an empty stub that simply returned without
cancelling the pending playback work item. The work function
f_audio_playback_work() accesses audio->lock, audio->play_queue and
audio->card which reside in the audio struct that is freed by
f_audio_free() after disable returns.

Fix by adding cancel_work_sync() to ensure the playback work item is
not in flight when the audio struct is freed.

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 | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/function/f_uac1_legacy.c
b/drivers/usb/gadget/function/f_uac1_legacy.c
index 6ad4b16769b7..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);
 }

 /*-------------------------------------------------------------------------*/
-- 
2.43.0

On Mon, May 25, 2026 at 9:30 AM Adrian Korwel <adriank20047@gmail.com> wrote:
>
> On Mon, May 26, 2026 at 12:57AM, Greg KH wrote:
> > Why is this not broken up into smaller patches...
> > The "changes" go below the --- line, right?
>
> Apologies for the formatting issues. Please find v3 below as a series
> of 4 patches. Fixes split into separate patches and changelog moved
> below the --- line.
>
> Adrian Korwel (4):
>   usb: gadget: f_uac1_legacy: fix file handle leaks in gaudio_open_snd_dev()
>   usb: gadget: f_uac1_legacy: fix use-after-free caused by bound guard
>   usb: gadget: f_uac1_legacy: cancel work in f_audio_disable()
>   usb: typec: thunderbolt: cancel work before altmode is removed
>
>  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 -
>  drivers/usb/typec/altmodes/thunderbolt.c    |  2 ++
>  4 files changed, 18 insertions(+), 10 deletions(-)
>
> On Mon, May 25, 2026 at 12:57 AM Greg KH <gregkh@linuxfoundation.org> wrote:
> >
> > On Sun, May 24, 2026 at 11:33:21PM -0500, Adrian Korwel wrote:
> > > 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.
> >
> > Why is this not broken up into smaller patches to corrispond with each
> > issue/fix?  Please do so.
> >
> >
> > >
> > > 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
> >
> > The "changes" go below the --- line, right?
> >
> > thanks,
> >
> > greg k-h

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

* Re: [PATCH v2] usb: gadget: f_uac1_legacy: fix use-after-free in gaudio_open_snd_dev()
  2026-05-25 14:30   ` Adrian Korwel
                       ` (2 preceding siblings ...)
  2026-05-25 14:36     ` Adrian Korwel
@ 2026-05-25 14:37     ` Adrian Korwel
  2026-05-25 19:08       ` Greg KH
  3 siblings, 1 reply; 20+ messages in thread
From: Adrian Korwel @ 2026-05-25 14:37 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-usb, stable, heikki.krogerus

[PATCH v3 4/4] usb: typec: thunderbolt: cancel work before altmode is removed

tbt_altmode_remove() frees resources associated with the Thunderbolt
altmode but does not cancel the pending work item before returning.
Since tbt is allocated with devm_kzalloc(), it is freed automatically
when the device is released after remove() returns.

The work item tbt_altmode_work() can be scheduled via schedule_work()
from tbt_altmode_vdm(), tbt_altmode_activate(), and the probe path,
and may still be pending or running when tbt_altmode_remove() returns.
The work function accesses tbt->lock, tbt->state, tbt->alt, and
tbt->plug[] — all of which reside in the freed struct, resulting in
a use-after-free.

Fix by calling cancel_work_sync() in tbt_altmode_remove() before
releasing any resources, ensuring no work item referencing tbt can
run after teardown begins.

Fixes: 100e25738659 ("usb: typec: Add driver for Thunderbolt 3 Alternate Mode")
Cc: stable@vger.kernel.org
Signed-off-by: Adrian Korwel <adriank20047@gmail.com>
---
 drivers/usb/typec/altmodes/thunderbolt.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/usb/typec/altmodes/thunderbolt.c
b/drivers/usb/typec/altmodes/thunderbolt.c
index 32250b94262a..57c8dff0c51f 100644
--- a/drivers/usb/typec/altmodes/thunderbolt.c
+++ b/drivers/usb/typec/altmodes/thunderbolt.c
@@ -303,6 +303,8 @@ static void tbt_altmode_remove(struct typec_altmode *alt)
 {
        struct tbt_altmode *tbt = typec_altmode_get_drvdata(alt);
+       cancel_work_sync(&tbt->work);
+
        for (int i = TYPEC_PLUG_SOP_PP; i >= 0; --i) {
                if (tbt->plug[i])
                        typec_altmode_put_plug(tbt->plug[i]);
-- 
2.43.0

On Mon, May 25, 2026 at 9:30 AM Adrian Korwel <adriank20047@gmail.com> wrote:
>
> On Mon, May 26, 2026 at 12:57AM, Greg KH wrote:
> > Why is this not broken up into smaller patches...
> > The "changes" go below the --- line, right?
>
> Apologies for the formatting issues. Please find v3 below as a series
> of 4 patches. Fixes split into separate patches and changelog moved
> below the --- line.
>
> Adrian Korwel (4):
>   usb: gadget: f_uac1_legacy: fix file handle leaks in gaudio_open_snd_dev()
>   usb: gadget: f_uac1_legacy: fix use-after-free caused by bound guard
>   usb: gadget: f_uac1_legacy: cancel work in f_audio_disable()
>   usb: typec: thunderbolt: cancel work before altmode is removed
>
>  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 -
>  drivers/usb/typec/altmodes/thunderbolt.c    |  2 ++
>  4 files changed, 18 insertions(+), 10 deletions(-)
>
> On Mon, May 25, 2026 at 12:57 AM Greg KH <gregkh@linuxfoundation.org> wrote:
> >
> > On Sun, May 24, 2026 at 11:33:21PM -0500, Adrian Korwel wrote:
> > > 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.
> >
> > Why is this not broken up into smaller patches to corrispond with each
> > issue/fix?  Please do so.
> >
> >
> > >
> > > 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
> >
> > The "changes" go below the --- line, right?
> >
> > thanks,
> >
> > greg k-h

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

* Re: [PATCH v2] usb: gadget: f_uac1_legacy: fix use-after-free in gaudio_open_snd_dev()
  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:26         ` [PATCH 1/4] usb: gadget: f_uac1_legacy: fix file handle leaks in gaudio_open_snd_dev() Adrian Korwel
  0 siblings, 2 replies; 20+ messages in thread
From: Greg KH @ 2026-05-25 19:08 UTC (permalink / raw)
  To: Adrian Korwel; +Cc: linux-usb, stable, heikki.krogerus

On Mon, May 25, 2026 at 09:37:52AM -0500, Adrian Korwel wrote:
> [PATCH v3 4/4] usb: typec: thunderbolt: cancel work before altmode is removed

Something went really wrong with this series, always use git send-email
or something else that can properly send patches :(

thanks,

greg k-h

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

* [PATCH 1/4] USB: serial: io_ti: fix heap overflow in build_i2c_fw_hdr()
  2026-05-25 19:08       ` Greg KH
@ 2026-05-25 20:24         ` 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
                             ` (6 more replies)
  2026-05-25 20:26         ` [PATCH 1/4] usb: gadget: f_uac1_legacy: fix file handle leaks in gaudio_open_snd_dev() Adrian Korwel
  1 sibling, 7 replies; 20+ messages in thread
From: Adrian Korwel @ 2026-05-25 20:24 UTC (permalink / raw)
  To: linux-usb; +Cc: gregkh, stable, heikki.krogerus, Adrian Korwel

build_i2c_fw_hdr() allocates a fixed-size buffer of
(16*1024 - 512) + sizeof(struct ti_i2c_firmware_rec) bytes, then
copies le16_to_cpu(img_header->Length) bytes into it without
validating that Length fits within the available space after the
firmware record header.

img_header->Length is a __le16 from the firmware file and can be
up to 65535. check_fw_sanity() validates the total firmware size
but not img_header->Length specifically.

Fix by rejecting images where img_header->Length exceeds the
available destination space.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Adrian Korwel <adriank20047@gmail.com>
---
 drivers/usb/serial/io_ti.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index a35409bd766c..afe29fdf9536 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -844,6 +844,11 @@ static int build_i2c_fw_hdr(u8 *header, const struct firmware *fw)
 	/* Pointer to fw_down memory image */
 	img_header = (struct ti_i2c_image_header *)&fw->data[4];
 
+	if (le16_to_cpu(img_header->Length) >
+			buffer_size - sizeof(struct ti_i2c_firmware_rec)) {
+		kfree(buffer);
+		return -EINVAL;
+	}
 	memcpy(buffer + sizeof(struct ti_i2c_firmware_rec),
 		&fw->data[4 + sizeof(struct ti_i2c_image_header)],
 		le16_to_cpu(img_header->Length));
-- 
2.43.0


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

* [PATCH 1/4] usb: gadget: f_uac1_legacy: fix file handle leaks in gaudio_open_snd_dev()
  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           ` Adrian Korwel
  2026-05-25 20:24           ` [PATCH 2/4] " Adrian Korwel
                             ` (5 subsequent siblings)
  6 siblings, 0 replies; 20+ messages in thread
From: Adrian Korwel @ 2026-05-25 20:24 UTC (permalink / raw)
  To: linux-usb; +Cc: gregkh, stable, heikki.krogerus, Adrian Korwel

gaudio_open_snd_dev() opens the ALSA control device file first, then
opens the PCM playback device. On two error paths the control file
handle is leaked:

When filp_open() for the playback device fails, the function returns
immediately without closing the already-opened control file handle.

When playback_default_hw_params() fails, its return value was ignored
and both the playback and control file handles were leaked.

Both leaks result in gaudio_cleanup() calling filp_close() on already
freed file objects, causing a use-after-free.

Fix by closing previously opened file handles before returning on
each error path, and by checking the return value of
playback_default_hw_params().

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/u_uac1_legacy.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

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;
-- 
2.43.0


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

* [PATCH 2/4] usb: gadget: f_uac1_legacy: fix file handle leaks in gaudio_open_snd_dev()
  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           ` 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
                             ` (4 subsequent siblings)
  6 siblings, 0 replies; 20+ messages in thread
From: Adrian Korwel @ 2026-05-25 20:24 UTC (permalink / raw)
  To: linux-usb; +Cc: gregkh, stable, heikki.krogerus, Adrian Korwel

gaudio_open_snd_dev() opens the ALSA control device file first, then
opens the PCM playback device. On two error paths the control file
handle is leaked:

When filp_open() for the playback device fails, the function returns
immediately without closing the already-opened control file handle.

When playback_default_hw_params() fails, its return value was ignored
and both the playback and control file handles were leaked.

Both leaks result in gaudio_cleanup() calling filp_close() on already
freed file objects, causing a use-after-free.

Fix by closing previously opened file handles before returning on
each error path, and by checking the return value of
playback_default_hw_params().

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/u_uac1_legacy.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

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;
-- 
2.43.0


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

* [PATCH 2/4] usb: gadget: f_uac1_legacy: fix use-after-free caused by bound guard
  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           ` Adrian Korwel
  2026-05-25 20:24           ` [PATCH 3/4] usb: gadget: f_uac1_legacy: cancel work in f_audio_disable() Adrian Korwel
                             ` (3 subsequent siblings)
  6 siblings, 0 replies; 20+ messages in thread
From: Adrian Korwel @ 2026-05-25 20:24 UTC (permalink / raw)
  To: linux-usb; +Cc: gregkh, stable, heikki.krogerus, Adrian Korwel

f_audio_bind() guards gaudio_setup() with an 'audio_opts->bound' flag
to prevent re-initialization on repeated bind attempts. However 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 by removing the bound guard and calling 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 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 | 11 ++++-------
 drivers/usb/gadget/function/u_uac1_legacy.h |  1 -
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/gadget/function/f_uac1_legacy.c b/drivers/usb/gadget/function/f_uac1_legacy.c
index 5d201a2e30e7..6ad4b16769b7 100644
--- a/drivers/usb/gadget/function/f_uac1_legacy.c
+++ b/drivers/usb/gadget/function/f_uac1_legacy.c
@@ -735,13 +735,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.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] 20+ messages in thread

* [PATCH 3/4] usb: gadget: f_uac1_legacy: cancel work in f_audio_disable()
  2026-05-25 20:24         ` [PATCH 1/4] USB: serial: io_ti: fix heap overflow in build_i2c_fw_hdr() Adrian Korwel
                             ` (2 preceding siblings ...)
  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           ` 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
                             ` (2 subsequent siblings)
  6 siblings, 0 replies; 20+ messages in thread
From: Adrian Korwel @ 2026-05-25 20:24 UTC (permalink / raw)
  To: linux-usb; +Cc: gregkh, stable, heikki.krogerus, Adrian Korwel

f_audio_disable() was an empty stub that simply returned without
cancelling the pending playback work item. The work function
f_audio_playback_work() accesses audio->lock, audio->play_queue and
audio->card which reside in the audio struct that is freed by
f_audio_free() after disable returns.

Fix by adding cancel_work_sync() to ensure the playback work item is
not in flight when the audio struct is freed.

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 | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/function/f_uac1_legacy.c b/drivers/usb/gadget/function/f_uac1_legacy.c
index 6ad4b16769b7..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);
 }
 
 /*-------------------------------------------------------------------------*/
-- 
2.43.0


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

* [PATCH 3/4] usb: gadget: f_uac1_legacy: fix use-after-free caused by bound guard
  2026-05-25 20:24         ` [PATCH 1/4] USB: serial: io_ti: fix heap overflow in build_i2c_fw_hdr() Adrian Korwel
                             ` (3 preceding siblings ...)
  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           ` 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
  6 siblings, 0 replies; 20+ messages in thread
From: Adrian Korwel @ 2026-05-25 20:24 UTC (permalink / raw)
  To: linux-usb; +Cc: gregkh, stable, heikki.krogerus, Adrian Korwel

f_audio_bind() guards gaudio_setup() with an 'audio_opts->bound' flag
to prevent re-initialization on repeated bind attempts. However 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 by removing the bound guard and calling 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 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 | 11 ++++-------
 drivers/usb/gadget/function/u_uac1_legacy.h |  1 -
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/gadget/function/f_uac1_legacy.c b/drivers/usb/gadget/function/f_uac1_legacy.c
index 5d201a2e30e7..6ad4b16769b7 100644
--- a/drivers/usb/gadget/function/f_uac1_legacy.c
+++ b/drivers/usb/gadget/function/f_uac1_legacy.c
@@ -735,13 +735,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.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] 20+ messages in thread

* [PATCH 4/4] usb: gadget: f_uac1_legacy: cancel work in f_audio_disable()
  2026-05-25 20:24         ` [PATCH 1/4] USB: serial: io_ti: fix heap overflow in build_i2c_fw_hdr() Adrian Korwel
                             ` (4 preceding siblings ...)
  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           ` Adrian Korwel
  2026-05-25 20:24           ` [PATCH 4/4] usb: typec: thunderbolt: cancel work before altmode is removed Adrian Korwel
  6 siblings, 0 replies; 20+ messages in thread
From: Adrian Korwel @ 2026-05-25 20:24 UTC (permalink / raw)
  To: linux-usb; +Cc: gregkh, stable, heikki.krogerus, Adrian Korwel

f_audio_disable() was an empty stub that simply returned without
cancelling the pending playback work item. The work function
f_audio_playback_work() accesses audio->lock, audio->play_queue and
audio->card which reside in the audio struct that is freed by
f_audio_free() after disable returns.

Fix by adding cancel_work_sync() to ensure the playback work item is
not in flight when the audio struct is freed.

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 | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/function/f_uac1_legacy.c b/drivers/usb/gadget/function/f_uac1_legacy.c
index 6ad4b16769b7..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);
 }
 
 /*-------------------------------------------------------------------------*/
-- 
2.43.0


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

* [PATCH 4/4] usb: typec: thunderbolt: cancel work before altmode is removed
  2026-05-25 20:24         ` [PATCH 1/4] USB: serial: io_ti: fix heap overflow in build_i2c_fw_hdr() Adrian Korwel
                             ` (5 preceding siblings ...)
  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           ` Adrian Korwel
  6 siblings, 0 replies; 20+ messages in thread
From: Adrian Korwel @ 2026-05-25 20:24 UTC (permalink / raw)
  To: linux-usb; +Cc: gregkh, stable, heikki.krogerus, Adrian Korwel

tbt_altmode_remove() frees resources associated with the Thunderbolt
altmode but does not cancel the pending work item before returning.
Since tbt is allocated with devm_kzalloc(), it is freed automatically
when the device is released after remove() returns.

The work item tbt_altmode_work() can be scheduled via schedule_work()
from tbt_altmode_vdm(), tbt_altmode_activate(), and the probe path,
and may still be pending or running when tbt_altmode_remove() returns.
The work function accesses tbt->lock, tbt->state, tbt->alt, and
tbt->plug[] — all of which reside in the freed struct, resulting in
a use-after-free.

Fix by calling cancel_work_sync() in tbt_altmode_remove() before
releasing any resources, ensuring no work item referencing tbt can
run after teardown begins.

Fixes: 100e25738659 ("usb: typec: Add driver for Thunderbolt 3 Alternate Mode")
Cc: stable@vger.kernel.org
Signed-off-by: Adrian Korwel <adriank20047@gmail.com>
---
 drivers/usb/typec/altmodes/thunderbolt.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/usb/typec/altmodes/thunderbolt.c b/drivers/usb/typec/altmodes/thunderbolt.c
index 32250b94262a..57c8dff0c51f 100644
--- a/drivers/usb/typec/altmodes/thunderbolt.c
+++ b/drivers/usb/typec/altmodes/thunderbolt.c
@@ -303,6 +303,8 @@ static void tbt_altmode_remove(struct typec_altmode *alt)
 {
 	struct tbt_altmode *tbt = typec_altmode_get_drvdata(alt);
 
+	cancel_work_sync(&tbt->work);
+
 	for (int i = TYPEC_PLUG_SOP_PP; i >= 0; --i) {
 		if (tbt->plug[i])
 			typec_altmode_put_plug(tbt->plug[i]);
-- 
2.43.0


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

* [PATCH 1/4] usb: gadget: f_uac1_legacy: fix file handle leaks in gaudio_open_snd_dev()
  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:26         ` 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
                             ` (2 more replies)
  1 sibling, 3 replies; 20+ messages in thread
From: Adrian Korwel @ 2026-05-25 20:26 UTC (permalink / raw)
  To: linux-usb; +Cc: gregkh, stable, heikki.krogerus, Adrian Korwel

gaudio_open_snd_dev() opens the ALSA control device file first, then
opens the PCM playback device. On two error paths the control file
handle is leaked:

When filp_open() for the playback device fails, the function returns
immediately without closing the already-opened control file handle.

When playback_default_hw_params() fails, its return value was ignored
and both the playback and control file handles were leaked.

Both leaks result in gaudio_cleanup() calling filp_close() on already
freed file objects, causing a use-after-free.

Fix by closing previously opened file handles before returning on
each error path, and by checking the return value of
playback_default_hw_params().

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/u_uac1_legacy.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

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;
-- 
2.43.0


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

* [PATCH 2/4] usb: gadget: f_uac1_legacy: fix use-after-free caused by bound guard
  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           ` 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
  2 siblings, 0 replies; 20+ messages in thread
From: Adrian Korwel @ 2026-05-25 20:26 UTC (permalink / raw)
  To: linux-usb; +Cc: gregkh, stable, heikki.krogerus, Adrian Korwel

f_audio_bind() guards gaudio_setup() with an 'audio_opts->bound' flag
to prevent re-initialization on repeated bind attempts. However 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 by removing the bound guard and calling 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 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 | 11 ++++-------
 drivers/usb/gadget/function/u_uac1_legacy.h |  1 -
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/gadget/function/f_uac1_legacy.c b/drivers/usb/gadget/function/f_uac1_legacy.c
index 5d201a2e30e7..6ad4b16769b7 100644
--- a/drivers/usb/gadget/function/f_uac1_legacy.c
+++ b/drivers/usb/gadget/function/f_uac1_legacy.c
@@ -735,13 +735,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.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] 20+ messages in thread

* [PATCH 3/4] usb: gadget: f_uac1_legacy: cancel work in f_audio_disable()
  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           ` Adrian Korwel
  2026-05-25 20:26           ` [PATCH 4/4] usb: typec: thunderbolt: cancel work before altmode is removed Adrian Korwel
  2 siblings, 0 replies; 20+ messages in thread
From: Adrian Korwel @ 2026-05-25 20:26 UTC (permalink / raw)
  To: linux-usb; +Cc: gregkh, stable, heikki.krogerus, Adrian Korwel

f_audio_disable() was an empty stub that simply returned without
cancelling the pending playback work item. The work function
f_audio_playback_work() accesses audio->lock, audio->play_queue and
audio->card which reside in the audio struct that is freed by
f_audio_free() after disable returns.

Fix by adding cancel_work_sync() to ensure the playback work item is
not in flight when the audio struct is freed.

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 | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/function/f_uac1_legacy.c b/drivers/usb/gadget/function/f_uac1_legacy.c
index 6ad4b16769b7..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);
 }
 
 /*-------------------------------------------------------------------------*/
-- 
2.43.0


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

* [PATCH 4/4] usb: typec: thunderbolt: cancel work before altmode is removed
  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           ` Adrian Korwel
  2 siblings, 0 replies; 20+ messages in thread
From: Adrian Korwel @ 2026-05-25 20:26 UTC (permalink / raw)
  To: linux-usb; +Cc: gregkh, stable, heikki.krogerus, Adrian Korwel

tbt_altmode_remove() frees resources associated with the Thunderbolt
altmode but does not cancel the pending work item before returning.
Since tbt is allocated with devm_kzalloc(), it is freed automatically
when the device is released after remove() returns.

The work item tbt_altmode_work() can be scheduled via schedule_work()
from tbt_altmode_vdm(), tbt_altmode_activate(), and the probe path,
and may still be pending or running when tbt_altmode_remove() returns.
The work function accesses tbt->lock, tbt->state, tbt->alt, and
tbt->plug[] — all of which reside in the freed struct, resulting in
a use-after-free.

Fix by calling cancel_work_sync() in tbt_altmode_remove() before
releasing any resources, ensuring no work item referencing tbt can
run after teardown begins.

Fixes: 100e25738659 ("usb: typec: Add driver for Thunderbolt 3 Alternate Mode")
Cc: stable@vger.kernel.org
Signed-off-by: Adrian Korwel <adriank20047@gmail.com>
---
 drivers/usb/typec/altmodes/thunderbolt.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/usb/typec/altmodes/thunderbolt.c b/drivers/usb/typec/altmodes/thunderbolt.c
index 32250b94262a..57c8dff0c51f 100644
--- a/drivers/usb/typec/altmodes/thunderbolt.c
+++ b/drivers/usb/typec/altmodes/thunderbolt.c
@@ -303,6 +303,8 @@ static void tbt_altmode_remove(struct typec_altmode *alt)
 {
 	struct tbt_altmode *tbt = typec_altmode_get_drvdata(alt);
 
+	cancel_work_sync(&tbt->work);
+
 	for (int i = TYPEC_PLUG_SOP_PP; i >= 0; --i) {
 		if (tbt->plug[i])
 			typec_altmode_put_plug(tbt->plug[i]);
-- 
2.43.0


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

end of thread, other threads:[~2026-05-25 20:26 UTC | newest]

Thread overview: 20+ 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-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

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