media: uvcvideo: Don't expose unsupported formats to userspace
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Thu, 20 Apr 2023 09:45:59 +0000 (10:45 +0100)
committerMauro Carvalho Chehab <mchehab@kernel.org>
Fri, 2 Jun 2023 17:48:02 +0000 (18:48 +0100)
When the uvcvideo driver encounters a format descriptor with an unknown
format GUID, it creates a corresponding struct uvc_format instance with
the fcc field set to 0. Since commit 50459f103edf ("media: uvcvideo:
Remove format descriptions"), the driver relies on the V4L2 core to
provide the format description string, which the V4L2 core can't do
without a valid 4CC. This triggers a WARN_ON.

As a format with a zero 4CC can't be selected, it is unusable for
applications. Ignore the format completely without creating a uvc_format
instance, which fixes the warning.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=217252
Link: https://bugzilla.redhat.com/show_bug.cgi?id=2180107
Fixes: 50459f103edf ("media: uvcvideo: Remove format descriptions")
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
drivers/media/usb/uvc/uvc_driver.c

index 7aefa76..d631ce4 100644 (file)
@@ -251,14 +251,17 @@ static int uvc_parse_format(struct uvc_device *dev,
                /* Find the format descriptor from its GUID. */
                fmtdesc = uvc_format_by_guid(&buffer[5]);
 
-               if (fmtdesc != NULL) {
-                       format->fcc = fmtdesc->fcc;
-               } else {
+               if (!fmtdesc) {
+                       /*
+                        * Unknown video formats are not fatal errors, the
+                        * caller will skip this descriptor.
+                        */
                        dev_info(&streaming->intf->dev,
                                 "Unknown video format %pUl\n", &buffer[5]);
-                       format->fcc = 0;
+                       return 0;
                }
 
+               format->fcc = fmtdesc->fcc;
                format->bpp = buffer[21];
 
                /*
@@ -675,7 +678,7 @@ static int uvc_parse_streaming(struct uvc_device *dev,
        interval = (u32 *)&frame[nframes];
 
        streaming->format = format;
-       streaming->nformats = nformats;
+       streaming->nformats = 0;
 
        /* Parse the format descriptors. */
        while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE) {
@@ -689,7 +692,10 @@ static int uvc_parse_streaming(struct uvc_device *dev,
                                &interval, buffer, buflen);
                        if (ret < 0)
                                goto error;
+                       if (!ret)
+                               break;
 
+                       streaming->nformats++;
                        frame += format->nframes;
                        format++;