[PATCH] usb: gadget: uvc: fix use-after-free in uvcg_extension_drop

Anuj Bolewar via B4 Relay <devnull+bolewara.gmail.com-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Newsgroups gmane.linux.usb.general,gmane.linux.kernel
Message-ID <[email protected]>
From: Anuj Bolewar <[email protected]>

uvcg_extension_drop() releases the configfs item reference with
config_item_put() and then removes the extension unit from the list and
frees its dynamic descriptor fields. When the put is the last reference,
config_item_cleanup() runs uvcg_extension_release(), which kfree()s the
struct uvcg_extension, so the subsequent list_del() and kfree() calls
dereference freed memory.

The configfs mkdir error path calls drop_item() on an item whose only
reference is the one held by the configfs hierarchy, so the put inside
drop_item() frees the unit synchronously and list_del() reads freed
memory (KASAN: slab-use-after-free Read in uvcg_extension_drop).

Do all the list and field cleanup while the item is still alive, and
release the reference as the last step.

Reported-by: syzbot+f093afc4e90b1908abdc-Pl5Pbv+GP7P466ipTTIvnc23WoclnBCfAL8bYrjMMd8@public.gmane.org
Closes: https://syzkaller.appspot.com/bug?extid=f093afc4e90b1908abdc
Fixes: 0525210c9840 ("usb: gadget: uvc: Allow definition of XUs in configfs")
Assisted-by: deepseek:v4-pro
Signed-off-by: Anuj Bolewar <[email protected]>
---
uvcg_extension_drop() releases the configfs item reference with
config_item_put() and then removes the extension unit from the list and
frees its dynamic descriptor fields. When that put is the last
reference, config_item_cleanup() runs uvcg_extension_release(), which
kfree()s the struct uvcg_extension, so the subsequent list_del()
dereferences freed memory.

The configfs mkdir error path calls drop_item() on an item whose only
reference is the one held by the configfs hierarchy, so the put inside
drop_item() frees the unit synchronously and list_del() then reads freed
memory (KASAN: slab-use-after-free Read in uvcg_extension_drop).

Fix it by doing all the list and field cleanup while the item is still
alive, and releasing the reference as the last step.
---
 drivers/usb/gadget/function/uvc_configfs.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c
index 70a1415ea40..65bad40ec6e 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -1256,11 +1256,12 @@ static void uvcg_extension_drop(struct config_group *group, struct config_item *
 
 	mutex_lock(&opts->lock);
 
-	config_item_put(item);
 	list_del(&xu->list);
 	kfree(xu->desc.baSourceID);
 	kfree(xu->desc.bmControls);
 
+	config_item_put(item);
+
 	mutex_unlock(&opts->lock);
 }
 

---
base-commit: 848acc8ffe1b7cd5f1bf427b93069becfebc2c9d
change-id: 20260804-uvc-extension-drop-uaf-26bfea1bc2d1

Best regards,
--  
Anuj Bolewar <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.