* [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