From: Sasha Levin Date: Mon, 13 Apr 2026 22:19:25 +0000 (-0400) Subject: drop 5 uvcvideo patches from queue-5.10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0ec3dbd23d406dab246e79d2ac2886a3eb3e8952;p=thirdparty%2Fkernel%2Fstable-queue.git drop 5 uvcvideo patches from queue-5.10 Dropped patches: - "media: uvcvideo: Move guid to entity" Queues: 5.10 Reason: dependency of dropped GPIO feature patch - "media: uvcvideo: Allow extra entities" Queues: 5.10 Reason: dependency of dropped GPIO feature patch - "media: uvcvideo: Implement UVC_EXT_GPIO_UNIT" Queues: 5.10 Reason: new feature not suitable for stable; maintainer NAK from Ben Hutchings, patch author Ricardo Ribalda agrees; missing bug fixes would introduce crash and memory leak Report: https://lore.kernel.org/stable/673ddf965a5af7b881e86cb2e22055d4fcbb2dfc.camel@decadent.org.uk/ - "media: uvcvideo: Mark invalid entities with id UVC_INVALID_ENTITY_ID" Queues: 5.10 Reason: depends on dropped GPIO feature patch (Stable-dep-of) - "media: uvcvideo: Use heuristic to find stream entity" Queues: 5.10 Reason: depends on dropped mark-invalid-entities patch --- diff --git a/queue-5.10/media-uvcvideo-allow-extra-entities.patch b/queue-5.10/media-uvcvideo-allow-extra-entities.patch deleted file mode 100644 index 6d51f4eac8..0000000000 --- a/queue-5.10/media-uvcvideo-allow-extra-entities.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 07f8d256b5d7918ca15aedb0d4ed4f81327b0c56 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 23 Dec 2020 14:35:18 +0100 -Subject: media: uvcvideo: Allow extra entities - -From: Ricardo Ribalda - -[ Upstream commit cae79e50d1222010fde8c522410c315f74d35c40 ] - -Increase the size of the id, to avoid collisions with entities -implemented by the driver that are not part of the UVC device. - -Entities exposed by the UVC device use IDs 0-255, extra entities -implemented by the driver (such as the GPIO entity) use IDs 256 and -up. - -Signed-off-by: Ricardo Ribalda -Signed-off-by: Laurent Pinchart -Signed-off-by: Mauro Carvalho Chehab -Stable-dep-of: 0e2ee70291e6 ("media: uvcvideo: Mark invalid entities with id UVC_INVALID_ENTITY_ID") -Signed-off-by: Sasha Levin ---- - drivers/media/usb/uvc/uvc_driver.c | 2 +- - drivers/media/usb/uvc/uvcvideo.h | 7 ++++++- - 2 files changed, 7 insertions(+), 2 deletions(-) - -diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c -index 15202269194ad..e1d3e753e80ed 100644 ---- a/drivers/media/usb/uvc/uvc_driver.c -+++ b/drivers/media/usb/uvc/uvc_driver.c -@@ -1037,7 +1037,7 @@ static const u8 uvc_media_transport_input_guid[16] = - UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT; - static const u8 uvc_processing_guid[16] = UVC_GUID_UVC_PROCESSING; - --static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id, -+static struct uvc_entity *uvc_alloc_entity(u16 type, u16 id, - unsigned int num_pads, unsigned int extra_size) - { - struct uvc_entity *entity; -diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h -index 656ab4d9356c2..0e4209dbf307f 100644 ---- a/drivers/media/usb/uvc/uvcvideo.h -+++ b/drivers/media/usb/uvc/uvcvideo.h -@@ -302,7 +302,12 @@ struct uvc_entity { - * chain. */ - unsigned int flags; - -- u8 id; -+ /* -+ * Entities exposed by the UVC device use IDs 0-255, extra entities -+ * implemented by the driver (such as the GPIO entity) use IDs 256 and -+ * up. -+ */ -+ u16 id; - u16 type; - char name[64]; - u8 guid[16]; --- -2.53.0 - diff --git a/queue-5.10/media-uvcvideo-implement-uvc_ext_gpio_unit.patch b/queue-5.10/media-uvcvideo-implement-uvc_ext_gpio_unit.patch deleted file mode 100644 index 559faea3a8..0000000000 --- a/queue-5.10/media-uvcvideo-implement-uvc_ext_gpio_unit.patch +++ /dev/null @@ -1,344 +0,0 @@ -From 58f94a0cfefa6086d22fd60e0fecced10d18967f Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 23 Dec 2020 14:35:22 +0100 -Subject: media: uvcvideo: Implement UVC_EXT_GPIO_UNIT - -From: Ricardo Ribalda - -[ Upstream commit 2886477ff98740cc3333cf785e4de0b1ff3d7a28 ] - -Some devices can implement a physical switch to disable the input of the -camera on demand. Think of it like an elegant privacy sticker. - -The system can read the status of the privacy switch via a GPIO. - -It is important to know the status of the switch, e.g. to notify the -user when the camera will produce black frames and a videochat -application is used. - -In some systems, the GPIO is connected to the main SoC instead of the -camera controller, with the connection reported by the system firmware -(ACPI or DT). In that case, the UVC device isn't aware of the GPIO. We -need to implement a virtual entity to handle the GPIO fully on the -driver side. - -For example, for ACPI-based systems, the GPIO is reported in the USB -device object: - - Scope (\_SB.PCI0.XHCI.RHUB.HS07) - { - - /.../ - - Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings - { - GpioIo (Exclusive, PullDefault, 0x0000, 0x0000, IoRestrictionOutputOnly, - "\\_SB.PCI0.GPIO", 0x00, ResourceConsumer, , - ) - { // Pin list - 0x0064 - } - }) - Name (_DSD, Package (0x02) // _DSD: Device-Specific Data - { - ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301") /* Device Properties for _DSD */, - Package (0x01) - { - Package (0x02) - { - "privacy-gpio", - Package (0x04) - { - \_SB.PCI0.XHCI.RHUB.HS07, - Zero, - Zero, - One - } - } - } - }) - } - -Signed-off-by: Ricardo Ribalda -Signed-off-by: Laurent Pinchart -Signed-off-by: Mauro Carvalho Chehab -Stable-dep-of: 0e2ee70291e6 ("media: uvcvideo: Mark invalid entities with id UVC_INVALID_ENTITY_ID") -Signed-off-by: Sasha Levin ---- - drivers/media/usb/uvc/uvc_ctrl.c | 3 + - drivers/media/usb/uvc/uvc_driver.c | 127 +++++++++++++++++++++++++++++ - drivers/media/usb/uvc/uvc_entity.c | 1 + - drivers/media/usb/uvc/uvcvideo.h | 16 ++++ - 4 files changed, 147 insertions(+) - -diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c -index 698bf5bb896ec..fc23e53c0d38b 100644 ---- a/drivers/media/usb/uvc/uvc_ctrl.c -+++ b/drivers/media/usb/uvc/uvc_ctrl.c -@@ -2378,6 +2378,9 @@ int uvc_ctrl_init_device(struct uvc_device *dev) - } else if (UVC_ENTITY_TYPE(entity) == UVC_ITT_CAMERA) { - bmControls = entity->camera.bmControls; - bControlSize = entity->camera.bControlSize; -+ } else if (UVC_ENTITY_TYPE(entity) == UVC_EXT_GPIO_UNIT) { -+ bmControls = entity->gpio.bmControls; -+ bControlSize = entity->gpio.bControlSize; - } - - /* Remove bogus/blacklisted controls */ -diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c -index e1d3e753e80ed..b86e46fa7c0af 100644 ---- a/drivers/media/usb/uvc/uvc_driver.c -+++ b/drivers/media/usb/uvc/uvc_driver.c -@@ -7,6 +7,7 @@ - */ - - #include -+#include - #include - #include - #include -@@ -1033,6 +1034,7 @@ static int uvc_parse_streaming(struct uvc_device *dev, - } - - static const u8 uvc_camera_guid[16] = UVC_GUID_UVC_CAMERA; -+static const u8 uvc_gpio_guid[16] = UVC_GUID_EXT_GPIO_CONTROLLER; - static const u8 uvc_media_transport_input_guid[16] = - UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT; - static const u8 uvc_processing_guid[16] = UVC_GUID_UVC_PROCESSING; -@@ -1064,6 +1066,9 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u16 id, - * is initialized by the caller. - */ - switch (type) { -+ case UVC_EXT_GPIO_UNIT: -+ memcpy(entity->guid, uvc_gpio_guid, 16); -+ break; - case UVC_ITT_CAMERA: - memcpy(entity->guid, uvc_camera_guid, 16); - break; -@@ -1467,6 +1472,108 @@ static int uvc_parse_control(struct uvc_device *dev) - return 0; - } - -+/* ----------------------------------------------------------------------------- -+ * Privacy GPIO -+ */ -+ -+static void uvc_gpio_event(struct uvc_device *dev) -+{ -+ struct uvc_entity *unit = dev->gpio_unit; -+ struct uvc_video_chain *chain; -+ u8 new_val; -+ -+ if (!unit) -+ return; -+ -+ new_val = gpiod_get_value_cansleep(unit->gpio.gpio_privacy); -+ -+ /* GPIO entities are always on the first chain. */ -+ chain = list_first_entry(&dev->chains, struct uvc_video_chain, list); -+ uvc_ctrl_status_event(chain, unit->controls, &new_val); -+} -+ -+static int uvc_gpio_get_cur(struct uvc_device *dev, struct uvc_entity *entity, -+ u8 cs, void *data, u16 size) -+{ -+ if (cs != UVC_CT_PRIVACY_CONTROL || size < 1) -+ return -EINVAL; -+ -+ *(u8 *)data = gpiod_get_value_cansleep(entity->gpio.gpio_privacy); -+ -+ return 0; -+} -+ -+static int uvc_gpio_get_info(struct uvc_device *dev, struct uvc_entity *entity, -+ u8 cs, u8 *caps) -+{ -+ if (cs != UVC_CT_PRIVACY_CONTROL) -+ return -EINVAL; -+ -+ *caps = UVC_CONTROL_CAP_GET | UVC_CONTROL_CAP_AUTOUPDATE; -+ return 0; -+} -+ -+static irqreturn_t uvc_gpio_irq(int irq, void *data) -+{ -+ struct uvc_device *dev = data; -+ -+ uvc_gpio_event(dev); -+ return IRQ_HANDLED; -+} -+ -+static int uvc_gpio_parse(struct uvc_device *dev) -+{ -+ struct uvc_entity *unit; -+ struct gpio_desc *gpio_privacy; -+ int irq; -+ -+ gpio_privacy = devm_gpiod_get_optional(&dev->udev->dev, "privacy", -+ GPIOD_IN); -+ if (IS_ERR_OR_NULL(gpio_privacy)) -+ return PTR_ERR_OR_ZERO(gpio_privacy); -+ -+ unit = uvc_alloc_entity(UVC_EXT_GPIO_UNIT, UVC_EXT_GPIO_UNIT_ID, 0, 1); -+ if (!unit) -+ return -ENOMEM; -+ -+ irq = gpiod_to_irq(gpio_privacy); -+ if (irq < 0) { -+ if (irq != EPROBE_DEFER) -+ dev_err(&dev->udev->dev, -+ "No IRQ for privacy GPIO (%d)\n", irq); -+ return irq; -+ } -+ -+ unit->gpio.gpio_privacy = gpio_privacy; -+ unit->gpio.irq = irq; -+ unit->gpio.bControlSize = 1; -+ unit->gpio.bmControls = (u8 *)unit + sizeof(*unit); -+ unit->gpio.bmControls[0] = 1; -+ unit->get_cur = uvc_gpio_get_cur; -+ unit->get_info = uvc_gpio_get_info; -+ strncpy(unit->name, "GPIO", sizeof(unit->name) - 1); -+ -+ list_add_tail(&unit->list, &dev->entities); -+ -+ dev->gpio_unit = unit; -+ -+ return 0; -+} -+ -+static int uvc_gpio_init_irq(struct uvc_device *dev) -+{ -+ struct uvc_entity *unit = dev->gpio_unit; -+ -+ if (!unit || unit->gpio.irq < 0) -+ return 0; -+ -+ return devm_request_threaded_irq(&dev->udev->dev, unit->gpio.irq, NULL, -+ uvc_gpio_irq, -+ IRQF_ONESHOT | IRQF_TRIGGER_FALLING | -+ IRQF_TRIGGER_RISING, -+ "uvc_privacy_gpio", dev); -+} -+ - /* ------------------------------------------------------------------------ - * UVC device scan - */ -@@ -1988,6 +2095,13 @@ static int uvc_scan_device(struct uvc_device *dev) - return -1; - } - -+ /* Add GPIO entity to the first chain. */ -+ if (dev->gpio_unit) { -+ chain = list_first_entry(&dev->chains, -+ struct uvc_video_chain, list); -+ list_add_tail(&dev->gpio_unit->chain, &chain->entities); -+ } -+ - return 0; - } - -@@ -2350,6 +2464,12 @@ static int uvc_probe(struct usb_interface *intf, - goto error; - } - -+ /* Parse the associated GPIOs. */ -+ if (uvc_gpio_parse(dev) < 0) { -+ uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC GPIOs\n"); -+ goto error; -+ } -+ - uvc_printk(KERN_INFO, "Found UVC %u.%02x device %s (%04x:%04x)\n", - dev->uvc_version >> 8, dev->uvc_version & 0xff, - udev->product ? udev->product : "", -@@ -2394,6 +2514,13 @@ static int uvc_probe(struct usb_interface *intf, - "supported.\n", ret); - } - -+ ret = uvc_gpio_init_irq(dev); -+ if (ret < 0) { -+ dev_err(&dev->udev->dev, -+ "Unable to request privacy GPIO IRQ (%d)\n", ret); -+ goto error; -+ } -+ - uvc_trace(UVC_TRACE_PROBE, "UVC device initialized.\n"); - usb_enable_autosuspend(udev); - return 0; -diff --git a/drivers/media/usb/uvc/uvc_entity.c b/drivers/media/usb/uvc/uvc_entity.c -index 7c9895377118c..96e965a16d061 100644 ---- a/drivers/media/usb/uvc/uvc_entity.c -+++ b/drivers/media/usb/uvc/uvc_entity.c -@@ -105,6 +105,7 @@ static int uvc_mc_init_entity(struct uvc_video_chain *chain, - case UVC_OTT_DISPLAY: - case UVC_OTT_MEDIA_TRANSPORT_OUTPUT: - case UVC_EXTERNAL_VENDOR_SPECIFIC: -+ case UVC_EXT_GPIO_UNIT: - default: - function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN; - break; -diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h -index 0e4209dbf307f..e9eef2170d866 100644 ---- a/drivers/media/usb/uvc/uvcvideo.h -+++ b/drivers/media/usb/uvc/uvcvideo.h -@@ -6,6 +6,7 @@ - #error "The uvcvideo.h header is deprecated, use linux/uvcvideo.h instead." - #endif /* __KERNEL__ */ - -+#include - #include - #include - #include -@@ -37,6 +38,8 @@ - (UVC_ENTITY_IS_TERM(entity) && \ - ((entity)->type & 0x8000) == UVC_TERM_OUTPUT) - -+#define UVC_EXT_GPIO_UNIT 0x7ffe -+#define UVC_EXT_GPIO_UNIT_ID 0x100 - - /* ------------------------------------------------------------------------ - * GUIDs -@@ -56,6 +59,9 @@ - #define UVC_GUID_UVC_SELECTOR \ - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02} -+#define UVC_GUID_EXT_GPIO_CONTROLLER \ -+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03} - - #define UVC_GUID_FORMAT_MJPEG \ - { 'M', 'J', 'P', 'G', 0x00, 0x00, 0x10, 0x00, \ -@@ -213,6 +219,7 @@ - * Structures. - */ - -+struct gpio_desc; - struct uvc_device; - - /* TODO: Put the most frequently accessed fields at the beginning of -@@ -354,6 +361,13 @@ struct uvc_entity { - u8 *bmControls; - u8 *bmControlsType; - } extension; -+ -+ struct { -+ u8 bControlSize; -+ u8 *bmControls; -+ struct gpio_desc *gpio_privacy; -+ int irq; -+ } gpio; - }; - - u8 bNrInPins; -@@ -696,6 +710,8 @@ struct uvc_device { - struct uvc_control *ctrl; - const void *data; - } async_ctrl; -+ -+ struct uvc_entity *gpio_unit; - }; - - enum uvc_handle_state { --- -2.53.0 - diff --git a/queue-5.10/media-uvcvideo-mark-invalid-entities-with-id-uvc_inv.patch b/queue-5.10/media-uvcvideo-mark-invalid-entities-with-id-uvc_inv.patch deleted file mode 100644 index 4ca2729383..0000000000 --- a/queue-5.10/media-uvcvideo-mark-invalid-entities-with-id-uvc_inv.patch +++ /dev/null @@ -1,316 +0,0 @@ -From 3d6f50159c10b15a3f774d28f2aa4576d10ae164 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 20 Aug 2025 16:08:16 +0000 -Subject: media: uvcvideo: Mark invalid entities with id UVC_INVALID_ENTITY_ID - -From: Thadeu Lima de Souza Cascardo - -[ Upstream commit 0e2ee70291e64a30fe36960c85294726d34a103e ] - -Per UVC 1.1+ specification 3.7.2, units and terminals must have a non-zero -unique ID. - -``` -Each Unit and Terminal within the video function is assigned a unique -identification number, the Unit ID (UID) or Terminal ID (TID), contained in -the bUnitID or bTerminalID field of the descriptor. The value 0x00 is -reserved for undefined ID, -``` - -If we add a new entity with id 0 or a duplicated ID, it will be marked -as UVC_INVALID_ENTITY_ID. - -In a previous attempt commit 3dd075fe8ebb ("media: uvcvideo: Require -entities to have a non-zero unique ID"), we ignored all the invalid units, -this broke a lot of non-compatible cameras. Hopefully we are more lucky -this time. - -This also prevents some syzkaller reproducers from triggering warnings due -to a chain of entities referring to themselves. In one particular case, an -Output Unit is connected to an Input Unit, both with the same ID of 1. But -when looking up for the source ID of the Output Unit, that same entity is -found instead of the input entity, which leads to such warnings. - -In another case, a backward chain was considered finished as the source ID -was 0. Later on, that entity was found, but its pads were not valid. - -Here is a sample stack trace for one of those cases. - -[ 20.650953] usb 1-1: new high-speed USB device number 2 using dummy_hcd -[ 20.830206] usb 1-1: Using ep0 maxpacket: 8 -[ 20.833501] usb 1-1: config 0 descriptor?? -[ 21.038518] usb 1-1: string descriptor 0 read error: -71 -[ 21.038893] usb 1-1: Found UVC 0.00 device (2833:0201) -[ 21.039299] uvcvideo 1-1:0.0: Entity type for entity Output 1 was not initialized! -[ 21.041583] uvcvideo 1-1:0.0: Entity type for entity Input 1 was not initialized! -[ 21.042218] ------------[ cut here ]------------ -[ 21.042536] WARNING: CPU: 0 PID: 9 at drivers/media/mc/mc-entity.c:1147 media_create_pad_link+0x2c4/0x2e0 -[ 21.043195] Modules linked in: -[ 21.043535] CPU: 0 UID: 0 PID: 9 Comm: kworker/0:1 Not tainted 6.11.0-rc7-00030-g3480e43aeccf #444 -[ 21.044101] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.15.0-1 04/01/2014 -[ 21.044639] Workqueue: usb_hub_wq hub_event -[ 21.045100] RIP: 0010:media_create_pad_link+0x2c4/0x2e0 -[ 21.045508] Code: fe e8 20 01 00 00 b8 f4 ff ff ff 48 83 c4 30 5b 41 5c 41 5d 41 5e 41 5f 5d c3 cc cc cc cc 0f 0b eb e9 0f 0b eb 0a 0f 0b eb 06 <0f> 0b eb 02 0f 0b b8 ea ff ff ff eb d4 66 2e 0f 1f 84 00 00 00 00 -[ 21.046801] RSP: 0018:ffffc9000004b318 EFLAGS: 00010246 -[ 21.047227] RAX: ffff888004e5d458 RBX: 0000000000000000 RCX: ffffffff818fccf1 -[ 21.047719] RDX: 000000000000007b RSI: 0000000000000000 RDI: ffff888004313290 -[ 21.048241] RBP: ffff888004313290 R08: 0001ffffffffffff R09: 0000000000000000 -[ 21.048701] R10: 0000000000000013 R11: 0001888004313290 R12: 0000000000000003 -[ 21.049138] R13: ffff888004313080 R14: ffff888004313080 R15: 0000000000000000 -[ 21.049648] FS: 0000000000000000(0000) GS:ffff88803ec00000(0000) knlGS:0000000000000000 -[ 21.050271] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 -[ 21.050688] CR2: 0000592cc27635b0 CR3: 000000000431c000 CR4: 0000000000750ef0 -[ 21.051136] PKRU: 55555554 -[ 21.051331] Call Trace: -[ 21.051480] -[ 21.051611] ? __warn+0xc4/0x210 -[ 21.051861] ? media_create_pad_link+0x2c4/0x2e0 -[ 21.052252] ? report_bug+0x11b/0x1a0 -[ 21.052540] ? trace_hardirqs_on+0x31/0x40 -[ 21.052901] ? handle_bug+0x3d/0x70 -[ 21.053197] ? exc_invalid_op+0x1a/0x50 -[ 21.053511] ? asm_exc_invalid_op+0x1a/0x20 -[ 21.053924] ? media_create_pad_link+0x91/0x2e0 -[ 21.054364] ? media_create_pad_link+0x2c4/0x2e0 -[ 21.054834] ? media_create_pad_link+0x91/0x2e0 -[ 21.055131] ? _raw_spin_unlock+0x1e/0x40 -[ 21.055441] ? __v4l2_device_register_subdev+0x202/0x210 -[ 21.055837] uvc_mc_register_entities+0x358/0x400 -[ 21.056144] uvc_register_chains+0x1fd/0x290 -[ 21.056413] uvc_probe+0x380e/0x3dc0 -[ 21.056676] ? __lock_acquire+0x5aa/0x26e0 -[ 21.056946] ? find_held_lock+0x33/0xa0 -[ 21.057196] ? kernfs_activate+0x70/0x80 -[ 21.057533] ? usb_match_dynamic_id+0x1b/0x70 -[ 21.057811] ? find_held_lock+0x33/0xa0 -[ 21.058047] ? usb_match_dynamic_id+0x55/0x70 -[ 21.058330] ? lock_release+0x124/0x260 -[ 21.058657] ? usb_match_one_id_intf+0xa2/0x100 -[ 21.058997] usb_probe_interface+0x1ba/0x330 -[ 21.059399] really_probe+0x1ba/0x4c0 -[ 21.059662] __driver_probe_device+0xb2/0x180 -[ 21.059944] driver_probe_device+0x5a/0x100 -[ 21.060170] __device_attach_driver+0xe9/0x160 -[ 21.060427] ? __pfx___device_attach_driver+0x10/0x10 -[ 21.060872] bus_for_each_drv+0xa9/0x100 -[ 21.061312] __device_attach+0xed/0x190 -[ 21.061812] device_initial_probe+0xe/0x20 -[ 21.062229] bus_probe_device+0x4d/0xd0 -[ 21.062590] device_add+0x308/0x590 -[ 21.062912] usb_set_configuration+0x7b6/0xaf0 -[ 21.063403] usb_generic_driver_probe+0x36/0x80 -[ 21.063714] usb_probe_device+0x7b/0x130 -[ 21.063936] really_probe+0x1ba/0x4c0 -[ 21.064111] __driver_probe_device+0xb2/0x180 -[ 21.064577] driver_probe_device+0x5a/0x100 -[ 21.065019] __device_attach_driver+0xe9/0x160 -[ 21.065403] ? __pfx___device_attach_driver+0x10/0x10 -[ 21.065820] bus_for_each_drv+0xa9/0x100 -[ 21.066094] __device_attach+0xed/0x190 -[ 21.066535] device_initial_probe+0xe/0x20 -[ 21.066992] bus_probe_device+0x4d/0xd0 -[ 21.067250] device_add+0x308/0x590 -[ 21.067501] usb_new_device+0x347/0x610 -[ 21.067817] hub_event+0x156b/0x1e30 -[ 21.068060] ? process_scheduled_works+0x48b/0xaf0 -[ 21.068337] process_scheduled_works+0x5a3/0xaf0 -[ 21.068668] worker_thread+0x3cf/0x560 -[ 21.068932] ? kthread+0x109/0x1b0 -[ 21.069133] kthread+0x197/0x1b0 -[ 21.069343] ? __pfx_worker_thread+0x10/0x10 -[ 21.069598] ? __pfx_kthread+0x10/0x10 -[ 21.069908] ret_from_fork+0x32/0x40 -[ 21.070169] ? __pfx_kthread+0x10/0x10 -[ 21.070424] ret_from_fork_asm+0x1a/0x30 -[ 21.070737] - -Reported-by: syzbot+0584f746fde3d52b4675@syzkaller.appspotmail.com -Closes: https://syzkaller.appspot.com/bug?extid=0584f746fde3d52b4675 -Reported-by: syzbot+dd320d114deb3f5bb79b@syzkaller.appspotmail.com -Closes: https://syzkaller.appspot.com/bug?extid=dd320d114deb3f5bb79b -Reported-by: Youngjun Lee -Fixes: a3fbc2e6bb05 ("media: mc-entity.c: use WARN_ON, validate link pads") -Cc: stable@vger.kernel.org -Signed-off-by: Thadeu Lima de Souza Cascardo -Co-developed-by: Ricardo Ribalda -Signed-off-by: Ricardo Ribalda -Reviewed-by: Laurent Pinchart -Reviewed-by: Hans de Goede -Signed-off-by: Hans de Goede -Signed-off-by: Laurent Pinchart -Signed-off-by: Hans Verkuil -Signed-off-by: Sasha Levin ---- - drivers/media/usb/uvc/uvc_driver.c | 73 +++++++++++++++++++----------- - drivers/media/usb/uvc/uvcvideo.h | 2 + - 2 files changed, 48 insertions(+), 27 deletions(-) - -diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c -index b86e46fa7c0af..bf1456caae2d2 100644 ---- a/drivers/media/usb/uvc/uvc_driver.c -+++ b/drivers/media/usb/uvc/uvc_driver.c -@@ -413,6 +413,9 @@ struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id) - { - struct uvc_entity *entity; - -+ if (id == UVC_INVALID_ENTITY_ID) -+ return NULL; -+ - list_for_each_entry(entity, &dev->entities, list) { - if (entity->id == id) - return entity; -@@ -1039,14 +1042,27 @@ static const u8 uvc_media_transport_input_guid[16] = - UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT; - static const u8 uvc_processing_guid[16] = UVC_GUID_UVC_PROCESSING; - --static struct uvc_entity *uvc_alloc_entity(u16 type, u16 id, -- unsigned int num_pads, unsigned int extra_size) -+static struct uvc_entity *uvc_alloc_new_entity(struct uvc_device *dev, u16 type, -+ u16 id, unsigned int num_pads, -+ unsigned int extra_size) - { - struct uvc_entity *entity; - unsigned int num_inputs; - unsigned int size; - unsigned int i; - -+ /* Per UVC 1.1+ spec 3.7.2, the ID should be non-zero. */ -+ if (id == 0) { -+ dev_err(&dev->intf->dev, "Found Unit with invalid ID 0\n"); -+ id = UVC_INVALID_ENTITY_ID; -+ } -+ -+ /* Per UVC 1.1+ spec 3.7.2, the ID is unique. */ -+ if (uvc_entity_by_id(dev, id)) { -+ dev_err(&dev->intf->dev, "Found multiple Units with ID %u\n", id); -+ id = UVC_INVALID_ENTITY_ID; -+ } -+ - extra_size = roundup(extra_size, sizeof(*entity->pads)); - if (num_pads) - num_inputs = type & UVC_TERM_OUTPUT ? num_pads : num_pads - 1; -@@ -1056,7 +1072,7 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u16 id, - + num_inputs; - entity = kzalloc(size, GFP_KERNEL); - if (entity == NULL) -- return NULL; -+ return ERR_PTR(-ENOMEM); - - entity->id = id; - entity->type = type; -@@ -1146,10 +1162,10 @@ static int uvc_parse_vendor_control(struct uvc_device *dev, - break; - } - -- unit = uvc_alloc_entity(UVC_VC_EXTENSION_UNIT, buffer[3], -- p + 1, 2*n); -- if (unit == NULL) -- return -ENOMEM; -+ unit = uvc_alloc_new_entity(dev, UVC_VC_EXTENSION_UNIT, -+ buffer[3], p + 1, 2 * n); -+ if (IS_ERR(unit)) -+ return PTR_ERR(unit); - - memcpy(unit->guid, &buffer[4], 16); - unit->extension.bNumControls = buffer[20]; -@@ -1260,10 +1276,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev, - return -EINVAL; - } - -- term = uvc_alloc_entity(type | UVC_TERM_INPUT, buffer[3], -- 1, n + p); -- if (term == NULL) -- return -ENOMEM; -+ term = uvc_alloc_new_entity(dev, type | UVC_TERM_INPUT, -+ buffer[3], 1, n + p); -+ if (IS_ERR(term)) -+ return PTR_ERR(term); - - if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) { - term->camera.bControlSize = n; -@@ -1319,10 +1335,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev, - return 0; - } - -- term = uvc_alloc_entity(type | UVC_TERM_OUTPUT, buffer[3], -- 1, 0); -- if (term == NULL) -- return -ENOMEM; -+ term = uvc_alloc_new_entity(dev, type | UVC_TERM_OUTPUT, -+ buffer[3], 1, 0); -+ if (IS_ERR(term)) -+ return PTR_ERR(term); - - memcpy(term->baSourceID, &buffer[7], 1); - -@@ -1343,9 +1359,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev, - return -EINVAL; - } - -- unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, 0); -- if (unit == NULL) -- return -ENOMEM; -+ unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3], -+ p + 1, 0); -+ if (IS_ERR(unit)) -+ return PTR_ERR(unit); - - memcpy(unit->baSourceID, &buffer[5], p); - -@@ -1367,9 +1384,9 @@ static int uvc_parse_standard_control(struct uvc_device *dev, - return -EINVAL; - } - -- unit = uvc_alloc_entity(buffer[2], buffer[3], 2, n); -- if (unit == NULL) -- return -ENOMEM; -+ unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3], 2, n); -+ if (IS_ERR(unit)) -+ return PTR_ERR(unit); - - memcpy(unit->baSourceID, &buffer[4], 1); - unit->processing.wMaxMultiplier = -@@ -1398,9 +1415,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev, - return -EINVAL; - } - -- unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, n); -- if (unit == NULL) -- return -ENOMEM; -+ unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3], -+ p + 1, n); -+ if (IS_ERR(unit)) -+ return PTR_ERR(unit); - - memcpy(unit->guid, &buffer[4], 16); - unit->extension.bNumControls = buffer[20]; -@@ -1532,9 +1550,10 @@ static int uvc_gpio_parse(struct uvc_device *dev) - if (IS_ERR_OR_NULL(gpio_privacy)) - return PTR_ERR_OR_ZERO(gpio_privacy); - -- unit = uvc_alloc_entity(UVC_EXT_GPIO_UNIT, UVC_EXT_GPIO_UNIT_ID, 0, 1); -- if (!unit) -- return -ENOMEM; -+ unit = uvc_alloc_new_entity(dev, UVC_EXT_GPIO_UNIT, -+ UVC_EXT_GPIO_UNIT_ID, 0, 1); -+ if (IS_ERR(unit)) -+ return PTR_ERR(unit); - - irq = gpiod_to_irq(gpio_privacy); - if (irq < 0) { -diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h -index e9eef2170d866..895db550f11db 100644 ---- a/drivers/media/usb/uvc/uvcvideo.h -+++ b/drivers/media/usb/uvc/uvcvideo.h -@@ -41,6 +41,8 @@ - #define UVC_EXT_GPIO_UNIT 0x7ffe - #define UVC_EXT_GPIO_UNIT_ID 0x100 - -+#define UVC_INVALID_ENTITY_ID 0xffff -+ - /* ------------------------------------------------------------------------ - * GUIDs - */ --- -2.53.0 - diff --git a/queue-5.10/media-uvcvideo-move-guid-to-entity.patch b/queue-5.10/media-uvcvideo-move-guid-to-entity.patch deleted file mode 100644 index 78ad1e3698..0000000000 --- a/queue-5.10/media-uvcvideo-move-guid-to-entity.patch +++ /dev/null @@ -1,160 +0,0 @@ -From 1dddd8f2ba7626eac0aca525e8d641a8599a76fb Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 23 Dec 2020 14:35:17 +0100 -Subject: media: uvcvideo: Move guid to entity - -From: Ricardo Ribalda - -[ Upstream commit 351509c604dcb065305a165d7552058c2cbc447d ] - -Instead of having multiple copies of the entity guid on the code, move -it to the entity structure. - -Signed-off-by: Ricardo Ribalda -Signed-off-by: Laurent Pinchart -Signed-off-by: Mauro Carvalho Chehab -Stable-dep-of: 0e2ee70291e6 ("media: uvcvideo: Mark invalid entities with id UVC_INVALID_ENTITY_ID") -Signed-off-by: Sasha Levin ---- - drivers/media/usb/uvc/uvc_ctrl.c | 30 ++++-------------------------- - drivers/media/usb/uvc/uvc_driver.c | 25 +++++++++++++++++++++++-- - drivers/media/usb/uvc/uvcvideo.h | 2 +- - 3 files changed, 28 insertions(+), 29 deletions(-) - -diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c -index 4f67ba3a7c028..698bf5bb896ec 100644 ---- a/drivers/media/usb/uvc/uvc_ctrl.c -+++ b/drivers/media/usb/uvc/uvc_ctrl.c -@@ -827,31 +827,10 @@ static void uvc_set_le_value(struct uvc_control_mapping *mapping, - * Terminal and unit management - */ - --static const u8 uvc_processing_guid[16] = UVC_GUID_UVC_PROCESSING; --static const u8 uvc_camera_guid[16] = UVC_GUID_UVC_CAMERA; --static const u8 uvc_media_transport_input_guid[16] = -- UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT; -- - static int uvc_entity_match_guid(const struct uvc_entity *entity, -- const u8 guid[16]) -+ const u8 guid[16]) - { -- switch (UVC_ENTITY_TYPE(entity)) { -- case UVC_ITT_CAMERA: -- return memcmp(uvc_camera_guid, guid, 16) == 0; -- -- case UVC_ITT_MEDIA_TRANSPORT_INPUT: -- return memcmp(uvc_media_transport_input_guid, guid, 16) == 0; -- -- case UVC_VC_PROCESSING_UNIT: -- return memcmp(uvc_processing_guid, guid, 16) == 0; -- -- case UVC_VC_EXTENSION_UNIT: -- return memcmp(entity->extension.guidExtensionCode, -- guid, 16) == 0; -- -- default: -- return 0; -- } -+ return memcmp(entity->guid, guid, sizeof(entity->guid)) == 0; - } - - /* ------------------------------------------------------------------------ -@@ -1882,8 +1861,7 @@ static int uvc_ctrl_fill_xu_info(struct uvc_device *dev, - if (data == NULL) - return -ENOMEM; - -- memcpy(info->entity, ctrl->entity->extension.guidExtensionCode, -- sizeof(info->entity)); -+ memcpy(info->entity, ctrl->entity->guid, sizeof(info->entity)); - info->index = ctrl->index; - info->selector = ctrl->index + 1; - -@@ -1989,7 +1967,7 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain, - - if (!found) { - uvc_trace(UVC_TRACE_CONTROL, "Control %pUl/%u not found.\n", -- entity->extension.guidExtensionCode, xqry->selector); -+ entity->guid, xqry->selector); - return -ENOENT; - } - -diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c -index 419fbdbb7a3b8..15202269194ad 100644 ---- a/drivers/media/usb/uvc/uvc_driver.c -+++ b/drivers/media/usb/uvc/uvc_driver.c -@@ -1032,6 +1032,11 @@ static int uvc_parse_streaming(struct uvc_device *dev, - return ret; - } - -+static const u8 uvc_camera_guid[16] = UVC_GUID_UVC_CAMERA; -+static const u8 uvc_media_transport_input_guid[16] = -+ UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT; -+static const u8 uvc_processing_guid[16] = UVC_GUID_UVC_PROCESSING; -+ - static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id, - unsigned int num_pads, unsigned int extra_size) - { -@@ -1054,6 +1059,22 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id, - entity->id = id; - entity->type = type; - -+ /* -+ * Set the GUID for standard entity types. For extension units, the GUID -+ * is initialized by the caller. -+ */ -+ switch (type) { -+ case UVC_ITT_CAMERA: -+ memcpy(entity->guid, uvc_camera_guid, 16); -+ break; -+ case UVC_ITT_MEDIA_TRANSPORT_INPUT: -+ memcpy(entity->guid, uvc_media_transport_input_guid, 16); -+ break; -+ case UVC_VC_PROCESSING_UNIT: -+ memcpy(entity->guid, uvc_processing_guid, 16); -+ break; -+ } -+ - entity->num_links = 0; - entity->num_pads = num_pads; - entity->pads = ((void *)(entity + 1)) + extra_size; -@@ -1125,7 +1146,7 @@ static int uvc_parse_vendor_control(struct uvc_device *dev, - if (unit == NULL) - return -ENOMEM; - -- memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); -+ memcpy(unit->guid, &buffer[4], 16); - unit->extension.bNumControls = buffer[20]; - memcpy(unit->baSourceID, &buffer[22], p); - unit->extension.bControlSize = buffer[22+p]; -@@ -1376,7 +1397,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev, - if (unit == NULL) - return -ENOMEM; - -- memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); -+ memcpy(unit->guid, &buffer[4], 16); - unit->extension.bNumControls = buffer[20]; - memcpy(unit->baSourceID, &buffer[22], p); - unit->extension.bControlSize = buffer[22+p]; -diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h -index 60a8749c97a9d..656ab4d9356c2 100644 ---- a/drivers/media/usb/uvc/uvcvideo.h -+++ b/drivers/media/usb/uvc/uvcvideo.h -@@ -305,6 +305,7 @@ struct uvc_entity { - u8 id; - u16 type; - char name[64]; -+ u8 guid[16]; - - /* Media controller-related fields. */ - struct video_device *vdev; -@@ -343,7 +344,6 @@ struct uvc_entity { - } selector; - - struct { -- u8 guidExtensionCode[16]; - u8 bNumControls; - u8 bControlSize; - u8 *bmControls; --- -2.53.0 - diff --git a/queue-5.10/media-uvcvideo-use-heuristic-to-find-stream-entity.patch b/queue-5.10/media-uvcvideo-use-heuristic-to-find-stream-entity.patch deleted file mode 100644 index 59d6943e3b..0000000000 --- a/queue-5.10/media-uvcvideo-use-heuristic-to-find-stream-entity.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 7d49628639436ec50d67f60938938e98ed23569c Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 21 Oct 2025 10:36:17 +0000 -Subject: media: uvcvideo: Use heuristic to find stream entity - -From: Ricardo Ribalda - -[ Upstream commit 758dbc756aad429da11c569c0d067f7fd032bcf7 ] - -Some devices, like the Grandstream GUV3100 webcam, have an invalid UVC -descriptor where multiple entities share the same ID, this is invalid -and makes it impossible to make a proper entity tree without heuristics. - -We have recently introduced a change in the way that we handle invalid -entities that has caused a regression on broken devices. - -Implement a new heuristic to handle these devices properly. - -Reported-by: Angel4005 -Closes: https://lore.kernel.org/linux-media/CAOzBiVuS7ygUjjhCbyWg-KiNx+HFTYnqH5+GJhd6cYsNLT=DaA@mail.gmail.com/ -Fixes: 0e2ee70291e6 ("media: uvcvideo: Mark invalid entities with id UVC_INVALID_ENTITY_ID") -Cc: stable@vger.kernel.org -Signed-off-by: Ricardo Ribalda -Reviewed-by: Hans de Goede -Signed-off-by: Hans Verkuil -Signed-off-by: Sasha Levin ---- - drivers/media/usb/uvc/uvc_driver.c | 15 ++++++++++++++- - 1 file changed, 14 insertions(+), 1 deletion(-) - -diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c -index bf1456caae2d2..5c07e79430e93 100644 ---- a/drivers/media/usb/uvc/uvc_driver.c -+++ b/drivers/media/usb/uvc/uvc_driver.c -@@ -443,13 +443,26 @@ static struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev, - - static struct uvc_streaming *uvc_stream_by_id(struct uvc_device *dev, int id) - { -- struct uvc_streaming *stream; -+ struct uvc_streaming *stream, *last_stream; -+ unsigned int count = 0; - - list_for_each_entry(stream, &dev->streams, list) { -+ count += 1; -+ last_stream = stream; - if (stream->header.bTerminalLink == id) - return stream; - } - -+ /* -+ * If the streaming entity is referenced by an invalid ID, notify the -+ * user and use heuristics to guess the correct entity. -+ */ -+ if (count == 1 && id == UVC_INVALID_ENTITY_ID) { -+ dev_warn(&dev->intf->dev, -+ "UVC non compliance: Invalid USB header. The streaming entity has an invalid ID, guessing the correct one."); -+ return last_stream; -+ } -+ - return NULL; - } - --- -2.53.0 - diff --git a/queue-5.10/series b/queue-5.10/series index c19fbefae9..07afb67209 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -422,11 +422,6 @@ mm-hugetlb-fix-hugetlb_pmd_shared.patch mm-hugetlb-fix-two-comments-related-to-huge_pmd_unsh.patch mm-rmap-fix-two-comments-related-to-huge_pmd_unshare.patch mm-hugetlb-fix-excessive-ipi-broadcasts-when-unshari.patch -media-uvcvideo-move-guid-to-entity.patch -media-uvcvideo-allow-extra-entities.patch -media-uvcvideo-implement-uvc_ext_gpio_unit.patch -media-uvcvideo-mark-invalid-entities-with-id-uvc_inv.patch -media-uvcvideo-use-heuristic-to-find-stream-entity.patch apparmor-validate-dfa-start-states-are-in-bounds-in-unpack_pdb.patch apparmor-fix-memory-leak-in-verify_header.patch apparmor-replace-recursive-profile-removal-with-iterative-approach.patch