[PATCH] media: gspca: check return value of usb_ifnum_to_if() in gspca_init_transfer()
From: Yuanzhe Liu
Date: Fri Oct 16 2026 - 00:05:18 EST
From: YuanZhe Liu <25031212351@xxxxxxxxxxxxxxxxx>
In gspca_init_transfer() and gspca_input_create_urb(), intf is looked up
via usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface). According to the
USB core implementation, usb_ifnum_to_if() returns NULL if the given
interface number is not found in the active configuration (for example,
if the device was disconnected or had its configuration reset).
Currently, neither function checks whether the returned intf pointer is
NULL before dereferencing its members. In gspca_init_transfer(), when
a bulk camera is used, intf->num_altsetting is dereferenced immediately;
for an isochronous camera, intf is passed into build_isoc_ep_tb(), which
also reads intf->num_altsetting unconditionally. This triggers a NULL
pointer dereference and results in a general protection fault crash.
In gspca_input_create_urb(), intf->cur_altsetting is likewise accessed
without checking for NULL.
Fix this by verifying that intf is non-NULL before dereferencing it.
Return -ENODEV in gspca_init_transfer() if intf is NULL, and return early
in gspca_input_create_urb().
Fixes: d43fa32fec44 ("V4L/DVB (8156): Many bug fixes, zc3xx added.")
Cc: stable@xxxxxxxxxxxxxxx
Co-developed-by: Bin Yu <byu@xxxxxxxxxxxxx>
Signed-off-by: Bin Yu <byu@xxxxxxxxxxxxx>
Co-developed-by: Cheng Wen <wencheng@xxxxxxxxxxxxx>
Signed-off-by: Cheng Wen <wencheng@xxxxxxxxxxxxx>
Signed-off-by: YuanZhe Liu <25031212351@xxxxxxxxxxxxxxxxx>
---
drivers/media/usb/gspca/gspca.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c
index 594d73e50b9f..1b76f871b672 100644
--- a/drivers/media/usb/gspca/gspca.c
+++ b/drivers/media/usb/gspca/gspca.c
@@ -213,6 +213,8 @@ static void gspca_input_create_urb(struct gspca_dev *gspca_dev)
if (gspca_dev->sd_desc->int_pkt_scan) {
intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
+ if (!intf)
+ return;
ret = usb_find_int_in_endpoint(intf->cur_altsetting, &ep);
if (ret)
@@ -765,6 +767,8 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
/* do the specific subdriver stuff before endpoint selection */
intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
+ if (!intf)
+ return -ENODEV;
gspca_dev->alt = gspca_dev->cam.bulk ? intf->num_altsetting : 0;
if (gspca_dev->sd_desc->isoc_init) {
ret = gspca_dev->sd_desc->isoc_init(gspca_dev);
--
2.34.1