Re: [PATCH RFC] usb: gadget: f_uac1, f_uac2: fix invalid free and memory leak

Aleksandr Nogikh <[email protected]> Wed, 29 Jul 2026 17:58:18 +0200
Newsgroups dev.linux.lists.syzbot
Message-ID <CANp29Y5URiKb-wanoAhy_57g9X9PkX07fOijeQ_tjMMMS7yqkg@mail.gmail.com>
#syz upstream

On Wed, Jul 29, 2026 at 5:14=E2=80=AFPM 'syzbot' via
syzkaller-upstream-moderation
<[email protected]> wrote:
>
> The `UAC1_RATE_ATTRIBUTE` and `UAC2_RATE_ATTRIBUTE` macros generate store
> functions that use `strsep()` to parse a comma-separated list of sample
> rates. The `strsep()` function modifies the pointer passed to it, advanci=
ng
> it past the delimiter.
>
> This causes two issues. First, if `kstrtou32()` fails (e.g., due to an
> invalid token), the code jumps to the `end` label and calls
> `kfree(split_page)`. Since `split_page` has been advanced by `strsep()`,
> this results in an invalid free. Second, if the loop completes
> successfully, `strsep()` sets `split_page` to `NULL`. The subsequent
> `kfree(split_page)` becomes a no-op, leaking the memory allocated by
> `kstrdup()`.
>
> KASAN reports the invalid free as follows:
>
> BUG: KASAN: invalid-free in f_uac2_opts_p_srate_store+0x225/0x2b0
> drivers/usb/gadget/function/f_uac2.c:2087
> Free of addr ffff888192cb7806 by task syz.0.17/6182
> Call Trace:
>  kfree+0x173/0x6c0 mm/slub.c:6692
>  f_uac2_opts_p_srate_store+0x225/0x2b0
>  drivers/usb/gadget/function/f_uac2.c:2087
>  flush_write_buffer fs/configfs/file.c:207 [inline]
>  configfs_write_iter+0x33a/0x430 fs/configfs/file.c:229
>  vfs_write+0x61e/0xbb0 fs/read_write.c:687
>  ksys_write+0x156/0x270 fs/read_write.c:739
> The buggy address is located 6 bytes inside of
>  32-byte region [ffff888192cb7800, ffff888192cb7820)
>
> Fix this by keeping the original pointer returned by `kstrdup()` in a
> separate variable `page_alloc` and passing a temporary pointer `split_pag=
e`
> to `strsep()`. This ensures that the correct pointer is passed to
> `kfree()`. Additionally, add a check to handle `kstrdup()` allocation
> failures.
>
> Fixes: a7339e4f5788 ("usb: gadget: f_uac2: Support multiple sampling rate=
s")
> Assisted-by: Gemini:gemini-3.5-flash Gemini:gemini-3.1-pro-preview syzbot
> Reported-by: [email protected]
> Closes: https://syzkaller.appspot.com/bug?extid=3Dbfca46c96ddf3b7d5c55
> Link: https://syzkaller.appspot.com/ai_job?id=3D705307cf-805c-4e75-8f76-2=
a0acc541cb8
> To: "Greg Kroah-Hartman" <[email protected]>
> To: <[email protected]>
> To: "Julian Scheel" <[email protected]>
> Cc: "Christophe JAILLET" <[email protected]>
> Cc: "Kees Cook" <[email protected]>
> Cc: <[email protected]>
>
> ---
> diff --git a/drivers/usb/gadget/function/f_uac1.c b/drivers/usb/gadget/fu=
nction/f_uac1.c
> index 85c502e98..f4b7bbd93 100644
> --- a/drivers/usb/gadget/function/f_uac1.c
> +++ b/drivers/usb/gadget/function/f_uac1.c
> @@ -1594,6 +1594,7 @@ static ssize_t f_uac1_opts_##name##_store(struct co=
nfig_item *item,       \
>                                           const char *page, size_t len) \
>  {                                                                      \
>         struct f_uac1_opts *opts =3D to_f_uac1_opts(item);               =
 \
> +       char *page_alloc =3D NULL;                                       =
 \
>         char *split_page =3D NULL;                                       =
 \
>         int ret =3D -EINVAL;                                             =
 \
>         char *token;                                                    \
> @@ -1608,7 +1609,12 @@ static ssize_t f_uac1_opts_##name##_store(struct c=
onfig_item *item,      \
>                                                                         \
>         i =3D 0;                                                         =
 \
>         memset(opts->name##s, 0x00, sizeof(opts->name##s));             \
> -       split_page =3D kstrdup(page, GFP_KERNEL);                        =
 \
> +       page_alloc =3D kstrdup(page, GFP_KERNEL);                        =
 \
> +       if (!page_alloc) {                                              \
> +               ret =3D -ENOMEM;                                         =
 \
> +               goto end;                                               \
> +       }                                                               \
> +       split_page =3D page_alloc;                                       =
 \
>         while ((token =3D strsep(&split_page, ",")) !=3D NULL) {         =
   \
>                 ret =3D kstrtou32(token, 0, &num);                       =
 \
>                 if (ret)                                                \
> @@ -1619,7 +1625,7 @@ static ssize_t f_uac1_opts_##name##_store(struct co=
nfig_item *item,       \
>         };                                                              \
>                                                                         \
>  end:                                                                   \
> -       kfree(split_page);                                              \
> +       kfree(page_alloc);                                              \
>         mutex_unlock(&opts->lock);                                      \
>         return ret;                                                     \
>  }                                                                      \
> diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/fu=
nction/f_uac2.c
> index 897787d08..336aeaec9 100644
> --- a/drivers/usb/gadget/function/f_uac2.c
> +++ b/drivers/usb/gadget/function/f_uac2.c
> @@ -2012,6 +2012,7 @@ static ssize_t f_uac2_opts_##name##_store(struct co=
nfig_item *item,       \
>                                           const char *page, size_t len) \
>  {                                                                      \
>         struct f_uac2_opts *opts =3D to_f_uac2_opts(item);               =
 \
> +       char *page_alloc =3D NULL;                                       =
 \
>         char *split_page =3D NULL;                                       =
 \
>         int ret =3D -EINVAL;                                             =
 \
>         char *token;                                                    \
> @@ -2026,7 +2027,12 @@ static ssize_t f_uac2_opts_##name##_store(struct c=
onfig_item *item,      \
>                                                                         \
>         i =3D 0;                                                         =
 \
>         memset(opts->name##s, 0x00, sizeof(opts->name##s));             \
> -       split_page =3D kstrdup(page, GFP_KERNEL);                        =
 \
> +       page_alloc =3D kstrdup(page, GFP_KERNEL);                        =
 \
> +       if (!page_alloc) {                                              \
> +               ret =3D -ENOMEM;                                         =
 \
> +               goto end;                                               \
> +       }                                                               \
> +       split_page =3D page_alloc;                                       =
 \
>         while ((token =3D strsep(&split_page, ",")) !=3D NULL) {         =
   \
>                 ret =3D kstrtou32(token, 0, &num);                       =
 \
>                 if (ret)                                                \
> @@ -2037,7 +2043,7 @@ static ssize_t f_uac2_opts_##name##_store(struct co=
nfig_item *item,       \
>         };                                                              \
>                                                                         \
>  end:                                                                   \
> -       kfree(split_page);                                              \
> +       kfree(page_alloc);                                              \
>         mutex_unlock(&opts->lock);                                      \
>         return ret;                                                     \
>  }                                                                      \
>
>
> base-commit: f5098b6bae761e346ebcd9da7f95622c04733cff
> --
> This is an AI-generated patch subject to moderation.
> Reply with '#syz upstream' to Sign-off the patch as a human author
> and send it to the upstream kernel mailing lists.
> Reply with '#syz reject' to reject it ('#syz unreject' to undo).
>
> See https://goo.gle/syzbot-ai-patches for information about AI-generated =
patches.
> You can comment on the patch as usual, syzbot will try to address
> the comments and send a new version of the patch if necessary.
> syzbot engineers can be reached at [email protected].
>
> --
> You received this message because you are subscribed to the Google Groups=
 "syzkaller-upstream-moderation" group.
> To unsubscribe from this group and stop receiving emails from it, send an=
 email to [email protected].
> To view this discussion visit https://groups.google.com/d/msgid/syzkaller=
-upstream-moderation/c0546d86-1fb7-46c5-a37d-645407387aeb%40mail.kernel.org=
.