Linux Media Controller development
 help / color / mirror / Atom feed
* [PATCH 0/2] media: uvcvideo: Fix two bugs on the control change event path
@ 2026-09-07  6:28 Wei Jie Law
  2026-09-07  6:28 ` [PATCH 1/2] media: uvcvideo: Fix NULL deref on events for uninitialized controls Wei Jie Law
  2026-09-07  6:28 ` [PATCH 2/2] media: uvcvideo: Fix out-of-bounds read in uvc_ctrl_status_event() Wei Jie Law
  0 siblings, 2 replies; 7+ messages in thread
From: Wei Jie Law @ 2026-09-07  6:28 UTC (permalink / raw)
  To: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab
  Cc: Guennadi Liakhovetski, linux-media, linux-kernel, stable

Two bugs on the UVC control change event path, both from e5225c820c05,
both in mainline and 6.12.y.

1/2 oopses on an event for an uninitialized XU control.  2/2 leaks heap
past the status buffer to userspace.  They are independent.

2/2 reports zero for a mapping that does not fit, as the compound case
already does.  Staging bValue into a zeroed buffer would give a truthful
value instead, if you prefer that.  6.12.y needs the same guard around
mapping->get().

Wei Jie Law (2):
  media: uvcvideo: Fix NULL deref on events for uninitialized controls
  media: uvcvideo: Fix out-of-bounds read in uvc_ctrl_status_event()

 drivers/media/usb/uvc/uvc_ctrl.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)


base-commit: a500db7819c50db59e55f1b4fa1c3baa5a2616f3
-- 
2.43.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/2] media: uvcvideo: Fix NULL deref on events for uninitialized controls
  2026-09-07  6:28 [PATCH 0/2] media: uvcvideo: Fix two bugs on the control change event path Wei Jie Law
@ 2026-09-07  6:28 ` Wei Jie Law
  2026-09-07  7:00   ` Ricardo Ribalda
  2026-09-07  6:28 ` [PATCH 2/2] media: uvcvideo: Fix out-of-bounds read in uvc_ctrl_status_event() Wei Jie Law
  1 sibling, 1 reply; 7+ messages in thread
From: Wei Jie Law @ 2026-09-07  6:28 UTC (permalink / raw)
  To: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab
  Cc: Guennadi Liakhovetski, linux-media, linux-kernel, stable

A null-ptr-deref exists in v6.12.105 and upstream. KASAN crash log:

  KASAN: null-ptr-deref in range [0x0000000000000080-0x0000000000000087]
  Workqueue: events uvc_ctrl_status_event_work
  RIP: 0010:uvc_ctrl_status_event+0x105/0x280
   uvc_ctrl_status_event_work+0x82/0x240
   process_one_work+0x66f/0x10b0

XU controls are initialized lazily, on the first UVCIOC_CTRL_MAP or
UVCIOC_CTRL_QUERY.  Until then ctrl->info is all zeroes, so
info.mappings is not a valid list head, list_empty() returns false, and
uvc_ctrl_status_event() walks it from a NULL next pointer.

Fixes: e5225c820c05 ("media: uvcvideo: Send a control event when a Control Change interrupt arrives")
Cc: stable@vger.kernel.org
Signed-off-by: Wei Jie Law <98lawweijie@gmail.com>
Assisted-by: Claude:claude-opus-5
---
 drivers/media/usb/uvc/uvc_ctrl.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
index 3ca108b83f1d..21802f9b1b61 100644
--- a/drivers/media/usb/uvc/uvc_ctrl.c
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
@@ -2209,7 +2209,12 @@ bool uvc_ctrl_status_event_async(struct urb *urb, struct uvc_video_chain *chain,
 	struct uvc_device *dev = chain->dev;
 	struct uvc_ctrl_work *w = &dev->async_ctrl;
 
-	if (list_empty(&ctrl->info.mappings))
+	/*
+	 * An uninitialized control has a zeroed info struct, so its
+	 * mappings list head is not a list: list_empty() returns false
+	 * and the walk dereferences NULL.
+	 */
+	if (!ctrl->initialized || list_empty(&ctrl->info.mappings))
 		return false;
 
 	w->data = data;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/2] media: uvcvideo: Fix out-of-bounds read in uvc_ctrl_status_event()
  2026-09-07  6:28 [PATCH 0/2] media: uvcvideo: Fix two bugs on the control change event path Wei Jie Law
  2026-09-07  6:28 ` [PATCH 1/2] media: uvcvideo: Fix NULL deref on events for uninitialized controls Wei Jie Law
@ 2026-09-07  6:28 ` Wei Jie Law
  2026-09-07  6:51   ` Ricardo Ribalda
  1 sibling, 1 reply; 7+ messages in thread
From: Wei Jie Law @ 2026-09-07  6:28 UTC (permalink / raw)
  To: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab
  Cc: Guennadi Liakhovetski, linux-media, linux-kernel, stable

An out-of-bounds read exists in v6.12.105 and upstream. KASAN crash log:

  BUG: KASAN: slab-use-after-free in uvc_get_le_value+0x314/0x350
  Read of size 1 at addr ffff88802df955e4 by task kworker/0:2/128
  Workqueue: events uvc_ctrl_status_event_work
   uvc_ctrl_status_event+0x128/0x280
   uvc_ctrl_status_event_work+0x82/0x240
  The buggy address belongs to the object at ffff88802df955e0
   which belongs to the cache kmalloc-16 of size 16

uvc_ctrl_add_mapping() validates mapping->offset against the control
data buffer, sized from the device's GET_LEN answer.
uvc_ctrl_status_event() applies the same offset to the 11 byte bValue
field of a control change event, so uvc_get_le_value() reads past the
16 byte struct uvc_status and the value is reported to userspace as a
V4L2_EVENT_CTRL change.  offset is a u8 bit offset, so the read reaches
24 bytes into the neighbouring objects; KASAN calls it a use-after-free
because the neighbour it read had just been freed.

Fixes: e5225c820c05 ("media: uvcvideo: Send a control event when a Control Change interrupt arrives")
Cc: stable@vger.kernel.org
Signed-off-by: Wei Jie Law <98lawweijie@gmail.com>
Assisted-by: Claude:claude-opus-5
---
 drivers/media/usb/uvc/uvc_ctrl.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
index 21802f9b1b61..d082bcb8d98d 100644
--- a/drivers/media/usb/uvc/uvc_ctrl.c
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
@@ -2156,11 +2156,16 @@ void uvc_ctrl_status_event(struct uvc_video_chain *chain,
 		uvc_ctrl_clear_handle(ctrl);
 
 	list_for_each_entry(mapping, &ctrl->info.mappings, list) {
-		s32 value;
+		s32 value = 0;
 
-		if (uvc_ctrl_mapping_is_compound(mapping))
-			value = 0;
-		else
+		/*
+		 * The offset is validated against the control size, not
+		 * against the event payload, so a mapping can reach past
+		 * bValue[].
+		 */
+		if (!uvc_ctrl_mapping_is_compound(mapping) &&
+		    mapping->offset + mapping->size <=
+			8 * sizeof_field(struct uvc_status_control, bValue))
 			value = uvc_mapping_get_s32(mapping, UVC_GET_CUR, data);
 
 		/*
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] media: uvcvideo: Fix out-of-bounds read in uvc_ctrl_status_event()
  2026-09-07  6:28 ` [PATCH 2/2] media: uvcvideo: Fix out-of-bounds read in uvc_ctrl_status_event() Wei Jie Law
@ 2026-09-07  6:51   ` Ricardo Ribalda
  2026-09-07  7:05     ` Wei Jie LAW
  0 siblings, 1 reply; 7+ messages in thread
From: Ricardo Ribalda @ 2026-09-07  6:51 UTC (permalink / raw)
  To: Wei Jie Law
  Cc: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab,
	Guennadi Liakhovetski, linux-media, linux-kernel, stable

Hi Wei


I belive this is already handled here:

https://lore.kernel.org/linux-media/20260813-uvc-status-11-v1-1-2cf43e9590b0@chromium.org/

On Mon, 7 Sept 2026 at 08:34, Wei Jie Law <98lawweijie@gmail.com> wrote:
>
> An out-of-bounds read exists in v6.12.105 and upstream. KASAN crash log:
>
>   BUG: KASAN: slab-use-after-free in uvc_get_le_value+0x314/0x350
>   Read of size 1 at addr ffff88802df955e4 by task kworker/0:2/128
>   Workqueue: events uvc_ctrl_status_event_work
>    uvc_ctrl_status_event+0x128/0x280
>    uvc_ctrl_status_event_work+0x82/0x240
>   The buggy address belongs to the object at ffff88802df955e0
>    which belongs to the cache kmalloc-16 of size 16
>
> uvc_ctrl_add_mapping() validates mapping->offset against the control
> data buffer, sized from the device's GET_LEN answer.
> uvc_ctrl_status_event() applies the same offset to the 11 byte bValue
> field of a control change event, so uvc_get_le_value() reads past the
> 16 byte struct uvc_status and the value is reported to userspace as a
> V4L2_EVENT_CTRL change.  offset is a u8 bit offset, so the read reaches
> 24 bytes into the neighbouring objects; KASAN calls it a use-after-free
> because the neighbour it read had just been freed.
>
> Fixes: e5225c820c05 ("media: uvcvideo: Send a control event when a Control Change interrupt arrives")
> Cc: stable@vger.kernel.org
> Signed-off-by: Wei Jie Law <98lawweijie@gmail.com>
> Assisted-by: Claude:claude-opus-5
> ---
>  drivers/media/usb/uvc/uvc_ctrl.c | 13 +++++++++----
>  1 file changed, 9 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
> index 21802f9b1b61..d082bcb8d98d 100644
> --- a/drivers/media/usb/uvc/uvc_ctrl.c
> +++ b/drivers/media/usb/uvc/uvc_ctrl.c
> @@ -2156,11 +2156,16 @@ void uvc_ctrl_status_event(struct uvc_video_chain *chain,
>                 uvc_ctrl_clear_handle(ctrl);
>
>         list_for_each_entry(mapping, &ctrl->info.mappings, list) {
> -               s32 value;
> +               s32 value = 0;
>
> -               if (uvc_ctrl_mapping_is_compound(mapping))
> -                       value = 0;
> -               else
> +               /*
> +                * The offset is validated against the control size, not
> +                * against the event payload, so a mapping can reach past
> +                * bValue[].
> +                */
> +               if (!uvc_ctrl_mapping_is_compound(mapping) &&
> +                   mapping->offset + mapping->size <=
> +                       8 * sizeof_field(struct uvc_status_control, bValue))
>                         value = uvc_mapping_get_s32(mapping, UVC_GET_CUR, data);
>
>                 /*
> --
> 2.43.0
>
>


-- 
Ricardo Ribalda

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] media: uvcvideo: Fix NULL deref on events for uninitialized controls
  2026-09-07  6:28 ` [PATCH 1/2] media: uvcvideo: Fix NULL deref on events for uninitialized controls Wei Jie Law
@ 2026-09-07  7:00   ` Ricardo Ribalda
  2026-09-07  8:12     ` Wei Jie LAW
  0 siblings, 1 reply; 7+ messages in thread
From: Ricardo Ribalda @ 2026-09-07  7:00 UTC (permalink / raw)
  To: Wei Jie Law
  Cc: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab,
	Guennadi Liakhovetski, linux-media, linux-kernel, stable

Hi Wei

On Mon, 7 Sept 2026 at 08:34, Wei Jie Law <98lawweijie@gmail.com> wrote:
>
> A null-ptr-deref exists in v6.12.105 and upstream. KASAN crash log:
>
>   KASAN: null-ptr-deref in range [0x0000000000000080-0x0000000000000087]
>   Workqueue: events uvc_ctrl_status_event_work
>   RIP: 0010:uvc_ctrl_status_event+0x105/0x280
>    uvc_ctrl_status_event_work+0x82/0x240
>    process_one_work+0x66f/0x10b0

Could you provide more info on how you reproduced the error?

>
> XU controls are initialized lazily, on the first UVCIOC_CTRL_MAP or
> UVCIOC_CTRL_QUERY.  Until then ctrl->info is all zeroes, so
> info.mappings is not a valid list head, list_empty() returns false, and
> uvc_ctrl_status_event() walks it from a NULL next pointer.
>
> Fixes: e5225c820c05 ("media: uvcvideo: Send a control event when a Control Change interrupt arrives")
> Cc: stable@vger.kernel.org
> Signed-off-by: Wei Jie Law <98lawweijie@gmail.com>
Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
> Assisted-by: Claude:claude-opus-5
> ---
>  drivers/media/usb/uvc/uvc_ctrl.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
> index 3ca108b83f1d..21802f9b1b61 100644
> --- a/drivers/media/usb/uvc/uvc_ctrl.c
> +++ b/drivers/media/usb/uvc/uvc_ctrl.c
> @@ -2209,7 +2209,12 @@ bool uvc_ctrl_status_event_async(struct urb *urb, struct uvc_video_chain *chain,
>         struct uvc_device *dev = chain->dev;
>         struct uvc_ctrl_work *w = &dev->async_ctrl;
>
> -       if (list_empty(&ctrl->info.mappings))
> +       /*
> +        * An uninitialized control has a zeroed info struct, so its
> +        * mappings list head is not a list: list_empty() returns false
> +        * and the walk dereferences NULL.
> +        */
nit: I would not add the comment.
> +       if (!ctrl->initialized || list_empty(&ctrl->info.mappings))
>                 return false;
>
>         w->data = data;
> --
> 2.43.0
>
>


-- 
Ricardo Ribalda

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] media: uvcvideo: Fix out-of-bounds read in uvc_ctrl_status_event()
  2026-09-07  6:51   ` Ricardo Ribalda
@ 2026-09-07  7:05     ` Wei Jie LAW
  0 siblings, 0 replies; 7+ messages in thread
From: Wei Jie LAW @ 2026-09-07  7:05 UTC (permalink / raw)
  To: ribalda
  Cc: 98lawweijie, guennadi.liakhovetski, hansg, laurent.pinchart,
	linux-kernel, linux-media, mchehab, stable

On Mon, 7 Sep 2026 08:51:45 Ricardo Ribalda <ribalda@chromium.org> wrote:

>
> Hi Wei
>
>
> I belive this is already handled here:
>
> https://lore.kernel.org/linux-media/20260813-uvc-status-11-v1-1-2cf43e9590b0@chromium.org/

You are right. I missed it out and the patches are logically the same.
Please ignore my patch request for this.

Regards,
Wei Jie

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] media: uvcvideo: Fix NULL deref on events for uninitialized controls
  2026-09-07  7:00   ` Ricardo Ribalda
@ 2026-09-07  8:12     ` Wei Jie LAW
  0 siblings, 0 replies; 7+ messages in thread
From: Wei Jie LAW @ 2026-09-07  8:12 UTC (permalink / raw)
  To: ribalda
  Cc: 98lawweijie, guennadi.liakhovetski, hansg, laurent.pinchart,
	linux-kernel, linux-media, mchehab, stable

On Mon, 7 Sept 2026 at 09:00:35, Ricardo Ribalda <ribalda@chromium.org> wrote:
> 
> Could you provide more info on how you reproduced the error?

The device I used is a Facedancer UVC gadget in a QEMU VM running
v6.12.105 + KASAN. It has:

  - a Video Control interface with an Extension Unit: id 3, one control
    declared in bmControls, GUID not matching any known mapping,
  - a status interrupt IN endpoint.

The crash is fully device-driven; from the host side the only
thing needed is a process that keeps the video device open -- any
camera application will do (no ioctl, and no privileges beyond normal
camera access: the opener can be any active desktop user).

Userspace never sends UVCIOC_CTRL_MAP / UVCIOC_CTRL_QUERY for that GUID,
so the XU control stays exactly as uvc_ctrl_init_chain() kzalloc'ed it
(XUs are initialized lazily by uvc_ctrl_init_ctrl(), which skips them).
Something then opens /dev/videoN, which arms the status URB, and the
device sends this 16-byte control change event:

  bStatusType  = 1 (control)
  bOriginator  = 3 (the XU)
  bEvent       = 0
  bSelector    = 0
  bAttribute   = 0 (VALUE_CHANGE)
  bValue[11]

The worker dies before it can resubmit the status URB, so one open()
gives one oops and the endpoint goes quiet; closing and reopening the
node repeats it. The oops does not depend on KASAN -- it is a plain NULL
walk on any kernel.

> nit: I would not add the comment.

Sure! Will remove the comments in a V2 patch, which I will submit later
along with the [2/2] patch request since it's a duplicate of yours.

Regards,
Wei Jie

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-09-07  8:12 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-07  6:28 [PATCH 0/2] media: uvcvideo: Fix two bugs on the control change event path Wei Jie Law
2026-09-07  6:28 ` [PATCH 1/2] media: uvcvideo: Fix NULL deref on events for uninitialized controls Wei Jie Law
2026-09-07  7:00   ` Ricardo Ribalda
2026-09-07  8:12     ` Wei Jie LAW
2026-09-07  6:28 ` [PATCH 2/2] media: uvcvideo: Fix out-of-bounds read in uvc_ctrl_status_event() Wei Jie Law
2026-09-07  6:51   ` Ricardo Ribalda
2026-09-07  7:05     ` Wei Jie LAW

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox