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