* [PATCH v3 0/4] media: uvcvideo: Map known XU controls
@ 2026-03-16 13:34 Ricardo Ribalda
2026-03-16 13:34 ` [PATCH v3 1/4] media: uvcvideo: Import standard controls from uvcdynctrl Ricardo Ribalda
` (3 more replies)
0 siblings, 4 replies; 15+ messages in thread
From: Ricardo Ribalda @ 2026-03-16 13:34 UTC (permalink / raw)
To: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab,
Greg Kroah-Hartman
Cc: linux-media, linux-kernel, linux-usb, Ricardo Ribalda,
Manav Gautama, Martin Rubli
The UVC driver uses a custom ioctl `UVCIOC_CTRL_MAP` to map XU controls
into v4l2 controls. The most well know user of this feature is the
uvcdynctrl app.
This app has a set of XML files which contains the list of mappings.
Some of these mappings are standard and other ones are custom.
This series move the standard mappings to the kernel driver, so
userspace do not need to depend on external apps to use them.
While we are at it we realized that some of the mappings can be harmful
for the privacy of the user. This series introduce a mechanism to block
those mappings.
While we are at it, we complete the deprecation of the nodrop parameter.
Ideally, this patch should belong in a different series, but then we
will have conflicts... and who wants to works twice?
I have tried this series with a Logitech Webcam Pro 9000, that has been
donated by Hans de Goede (Thanks Hans!!!).
Without this patch and uvcdynctrl the device has 14 controls. (Ctrls A)
With this patch the device has 15 controls (Ctrls B):
Ctrls A
+
control 0x009a090a `Focus, Absolute' min 0 max 255 step 0 default 0 current 0
With uvcdynctrl and this patch the device has 17 controls (Ctrls C):
Ctrls B
+
control 0x0a046d71 `Disable video processing' min 0 max 1 step 1 default 0 current 0
control 0x0a046d72 `Raw bits per pixel' min 0 max 1 step 1 default 0 current 0
With uvcdynctrl and without this patch the device has 19 controls:
Ctrls C
+
control 0x0a046d05 `LED1 Mode' min 0 max 3 step 1 default 3 current 3
0: Off
1: On
2: Blinking
3: Auto (*)
control 0x0a046d06 `LED1 Frequency' min 0 max 255 step 1 default 0 current 0
BTW, Driver tested with virtme-ng. First time that I use it for uvc
development, and it works like a charm :).
virtme-run --kimg arch/x86/boot/bzImage --mods auto --show-command \
--show-boot-console --verbose --qemu-opts -usb -device qemu-xhci \
-device usb-host,hostbus=1,hostport=4
Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
---
Changes in v3:
- s/param/module parameter/ (Thanks HdG)
- Rebase to lastest media-committers/next and remove merged patches.
- Link to v2: https://lore.kernel.org/r/20251119-uvcdynctrl-v2-0-0359ffb98c9e@chromium.org
Changes in v2:
- Document how to get GUIDs
- Show clear deprecation intentions to the user.
- Add new patch for the Kconfig approach (Thanks Mauro).
- Remove duplicated control in commit message, provide background and
add documentation. (Thanks Laurent)
- Block also uvc_query_ctrl for privacy controls (Thanks Gergo Koteles)
- Link to v1: https://lore.kernel.org/r/20251117-uvcdynctrl-v1-0-aed70eadf3d8@chromium.org
---
Ricardo Ribalda (4):
media: uvcvideo: Import standard controls from uvcdynctrl
media: uvcvideo: Announce deprecation intentions for UVCIOC_CTRL_MAP
media: uvcvideo: Introduce allow_privacy_override module parameter
media: uvcvideo: RFC: Convert allow_privacy_override into Kconfig
.../userspace-api/media/drivers/uvcvideo.rst | 2 +
drivers/media/usb/uvc/Kconfig | 11 ++
drivers/media/usb/uvc/uvc_ctrl.c | 212 +++++++++++++++++++++
drivers/media/usb/uvc/uvc_v4l2.c | 11 ++
drivers/media/usb/uvc/uvcvideo.h | 1 +
include/linux/usb/uvc.h | 10 +
6 files changed, 247 insertions(+)
---
base-commit: f6390408a846aacc2171c17d88b062e202d84e86
change-id: 20251117-uvcdynctrl-7b80f5bfbb41
Best regards,
--
Ricardo Ribalda <ribalda@chromium.org>
^ permalink raw reply [flat|nested] 15+ messages in thread* [PATCH v3 1/4] media: uvcvideo: Import standard controls from uvcdynctrl 2026-03-16 13:34 [PATCH v3 0/4] media: uvcvideo: Map known XU controls Ricardo Ribalda @ 2026-03-16 13:34 ` Ricardo Ribalda 2026-03-16 13:34 ` [PATCH v3 2/4] media: uvcvideo: Announce deprecation intentions for UVCIOC_CTRL_MAP Ricardo Ribalda ` (2 subsequent siblings) 3 siblings, 0 replies; 15+ messages in thread From: Ricardo Ribalda @ 2026-03-16 13:34 UTC (permalink / raw) To: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman Cc: linux-media, linux-kernel, linux-usb, Ricardo Ribalda, Manav Gautama, Martin Rubli The uvcdynctrl tool from libwebcam: https://sourceforge.net/projects/libwebcam/ maps proprietary controls into v4l2 controls using the UVCIOC_CTRL_MAP ioctl. The tool has not been updated for 10+ years now, and there is no reason for the UVC driver to not do the mapping by itself. This patch adds the mappings from the uvcdynctrl into the driver. Hopefully this effort can help in deprecating the UVCIOC_CTRL_MAP ioctl. Some background about UVCIOC_CTRL_MAP (thanks Laurent for the context): ``` this was envisioned as the base of a vibrant ecosystem where a large number of vendors would submit XML files that describe their XU control mappings, at a pace faster than could be supported by adding XU mappings to the driver. This vision failed to materialize and the tool has not been updated for 10+ years now. There is no reason to believe the situation will change. ``` During the porting, the following mappings where NOT imported because they were not using standard v4l2 IDs. It is recommended that userspace moves to UVCIOC_CTRL_QUERY for non standard controls. { .id = V4L2_CID_FLASH_MODE, .entity = UVC_GUID_SIS_LED_HW_CONTROL, .selector = 4, .size = 4, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_MENU, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, .menu_mask = 0x3, .menu_mapping = { 0x20, 0x22 }, .menu_names = { "Off", "On" }, }, { .id = V4L2_CID_FLASH_FREQUENCY, .entity = UVC_GUID_SIS_LED_HW_CONTROL, .selector = 4, .size = 8, .offset = 16, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id = V4L2_CID_LED1_MODE, .entity = UVC_GUID_LOGITECH_USER_HW_CONTROL_V1, .selector = 1, .size = 8, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_MENU, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, .menu_mask = 0xF, .menu_mapping = { 0, 1, 2, 3 }, .menu_names = { "Off", "On", "Blinking", "Auto" }, }, { .id = V4L2_CID_LED1_FREQUENCY, .entity = UVC_GUID_LOGITECH_USER_HW_CONTROL_V1, .selector = 1, .size = 8, .offset = 16, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id = V4L2_CID_DISABLE_PROCESSING, .entity = UVC_GUID_LOGITECH_VIDEO_PIPE_V1, .selector = 5, .size = 8, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, }, { .id = V4L2_CID_RAW_BITS_PER_PIXEL, .entity = UVC_GUID_LOGITECH_VIDEO_PIPE_V1, .selector = 8, .size = 8, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id = V4L2_CID_LED1_MODE, .entity = UVC_GUID_LOGITECH_PERIPHERAL, .selector = 0x09, .size = 2, .offset = 8, .v4l2_type = V4L2_CTRL_TYPE_MENU, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, .menu_mask = 0xF, .menu_mapping = { 0, 1, 2, 3 }, .menu_names = { "Off", "On", "Blink", "Auto" }, }, { .id = V4L2_CID_LED1_FREQUENCY, .entity = UVC_GUID_LOGITECH_PERIPHERAL, .selector = 0x09, .size = 8, .offset = 24, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, }, This script has been used to generate the mappings. They were then reformatted manually to follow the driver style. import sys import uuid import re import xml.etree.ElementTree as ET def get_namespace(root): return re.match(r"\{.*\}", root.tag).group(0) def get_single_guid(ns, constant): id = constant.find(ns + "id").text value = constant.find(ns + "value").text return (id, value) def get_constants(ns, root): out = dict() for constant in root.iter(ns + "constant"): attr = constant.attrib if attr["type"] == "integer": id, value = get_single_guid(ns, constant) if id in out: print(f"dupe constant {id}") out[id] = value return out def get_guids(ns, root): out = dict() for constant in root.iter(ns + "constant"): attr = constant.attrib if attr["type"] == "guid": id, value = get_single_guid(ns, constant) if id in out: print(f"dupe guid {id}") out[id] = value return out def get_single_control(ns, control): out = {} for id in "entity", "selector", "index", "size", "description": v = control.find(ns + id) if v is None and id == "description": continue out[id] = v.text reqs = set() for r in control.find(ns + "requests"): reqs.add(r.text) out["requests"] = reqs return (control.attrib["id"], out) def get_controls(ns, root): out = dict() for control in root.iter(ns + "control"): id, value = get_single_control(ns, control) if id in out: print(f"Dupe control id {id}") out[id] = value return out def get_single_mapping(ns, mapping): out = {} out["name"] = mapping.find(ns + "name").text uvc = mapping.find(ns + "uvc") for id in "size", "offset", "uvc_type": out[id] = uvc.find(ns + id).text out["control_ref"] = uvc.find(ns + "control_ref").attrib["idref"] v4l2 = mapping.find(ns + "v4l2") for id in "id", "v4l2_type": out[id] = v4l2.find(ns + id).text menu = {} for entry in v4l2.iter(ns + "menu_entry"): menu[entry.attrib["name"]] = entry.attrib["value"] if menu: out["menu"] = menu return out def get_mapping(ns, root): out = [] for control in root.iter(ns + "mapping"): mapping = get_single_mapping(ns, control) out += [mapping] return out def print_guids(guids): for g in guids: print(f"#define {g} \\") u_bytes = uuid.UUID(guids[g]).bytes_le u_bytes = [f"0x{b:02x}" for b in u_bytes] print("\t{ " + ", ".join(u_bytes) + " }") def print_flags(flags): get_range = {"GET_MIN", "GET_DEF", "GET_MAX", "GET_CUR", "GET_RES"} if get_range.issubset(flags): flags -= get_range flags.add("GET_RANGE") flags = list(flags) flags.sort() out = "" for f in flags[:-1]: out += f"UVC_CTRL_FLAG_{f}\n\t\t\t\t| " out += f"UVC_CTRL_FLAG_{flags[-1]}" return out def print_description(desc): print("/*") for line in desc.strip().splitlines(): print(f" * {line.strip()}") print("*/") def print_controls(controls, cons): for id in controls: c = controls[id] if "description" in c: print_description(c["description"]) print( f"""\t{{ \t\t.entity\t\t= {c["entity"]}, \t\t.selector\t= {cons[c["selector"]]}, \t\t.index\t\t= {c["index"]}, \t\t.size\t\t= {c["size"]}, \t\t.flags\t\t= {print_flags(c["requests"])}, \t}},""" ) def menu_mapping_txt(menu): out = f"\n\t\t.menu_mask\t= 0x{((1<<len(menu))-1):X},\n" out += f"\t\t.menu_mapping\t= {{ {", ".join(menu.values())} }},\n" out += f"\t\t.menu_names\t= {{ \"{"\", \"".join(menu.keys())}\" }},\n" return out def print_mappings(mappings, controls, cons): for m in mappings: c = controls[m["control_ref"]] if "menu" in m: menu_mapping = menu_mapping_txt(m["menu"]) else: menu_mapping = "" print( f"""\t{{ \t\t.id\t\t= {m["id"]}, \t\t.entity\t\t= {c["entity"]}, \t\t.selector\t= {cons[c["selector"]]}, \t\t.size\t\t= {m["size"]}, \t\t.offset\t\t= {m["offset"]}, \t\t.v4l2_type\t= {m["v4l2_type"]}, \t\t.data_type\t= {m["uvc_type"]},{menu_mapping} \t}},""" ) def print_code(guids, cons, controls, mappings): used_controls = set() for m in mappings: used_controls.add(m["control_ref"]) used_guids = set() for c in used_controls: used_guids.add(controls[c]["entity"]) print("\n######GUIDs#######\n") print_guids({id: guids[id] for id in guids if id in used_guids}) print("\n######CONTROLS#######\n") print_controls({id: controls[id] for id in controls if id in used_controls}, cons) print("\n######MAPPINGS#######\n") print_mappings(mappings, controls, cons) # print(guids) # print(used_controls) root = ET.fromstring(sys.stdin.read()) ns = get_namespace(root) cons = get_constants(ns, root) guids = get_guids(ns, root) controls = get_controls(ns, root) mappings = get_mapping(ns, root) print_code(guids, cons, controls, mappings) Cc: Manav Gautama <bandwidthcrunch@gmail.com> Cc: Martin Rubli <martin_rubli@logitech.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> --- drivers/media/usb/uvc/uvc_ctrl.c | 174 +++++++++++++++++++++++++++++++++++++++ include/linux/usb/uvc.h | 6 ++ 2 files changed, 180 insertions(+) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index b9a3d9257a11..b6e020b41671 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -385,6 +385,99 @@ static const struct uvc_control_info uvc_ctrls[] = { | UVC_CTRL_FLAG_GET_RANGE | UVC_CTRL_FLAG_RESTORE, }, + /* + * Allows the control of pan/tilt motor movements for camera models + * that support mechanical pan/tilt. + * + * Bits 0 to 15 control pan, bits 16 to 31 control tilt. + * The unit of the pan/tilt values is 1/64th of a degree and the + * resolution is 1 degree. + */ + { + .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector = 1, + .index = 0, + .size = 4, + .flags = UVC_CTRL_FLAG_GET_DEF + | UVC_CTRL_FLAG_GET_MAX + | UVC_CTRL_FLAG_GET_MIN + | UVC_CTRL_FLAG_SET_CUR, + }, + /* + * Reset the pan/tilt motors to their original position for camera + * models that support mechanical pan/tilt. + * + * Setting bit 0 resets the pan position. + * Setting bit 1 resets the tilt position. + * + * Both bits can be set at the same time to reset both, pan and tilt, + * at the same time. + */ + { + .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector = 2, + .index = 1, + .size = 1, + .flags = UVC_CTRL_FLAG_GET_DEF + | UVC_CTRL_FLAG_GET_MAX + | UVC_CTRL_FLAG_GET_MIN + | UVC_CTRL_FLAG_SET_CUR, + }, + /* + * Allows the control of focus motor movements for camera models that + * support mechanical focus. + * + * Bits 0 to 7 allow selection of the desired lens position. + * There are no physical units, instead, the focus range is spread over + * 256 logical units with 0 representing infinity focus and 255 being + * macro focus. + */ + { + .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector = 3, + .index = 2, + .size = 6, + .flags = UVC_CTRL_FLAG_GET_CUR + | UVC_CTRL_FLAG_GET_DEF + | UVC_CTRL_FLAG_GET_MAX + | UVC_CTRL_FLAG_GET_MIN + | UVC_CTRL_FLAG_SET_CUR, + }, + /* + * Allows the control of pan/tilt motor movements for camera models + * that support mechanical pan/tilt. + * + * Bits 0 to 15 control pan, bits 16 to 31 control tilt. + */ + { + .entity = UVC_GUID_LOGITECH_PERIPHERAL, + .selector = 1, + .index = 0, + .size = 4, + .flags = UVC_CTRL_FLAG_GET_DEF + | UVC_CTRL_FLAG_GET_MAX + | UVC_CTRL_FLAG_GET_MIN + | UVC_CTRL_FLAG_GET_RES + | UVC_CTRL_FLAG_SET_CUR, + }, + /* + * Reset the pan/tilt motors to their original position for camera + * models that support mechanical pan/tilt. + * + * Setting bit 0 resets the pan position. + * Setting bit 1 resets the tilt position. + */ + { + .entity = UVC_GUID_LOGITECH_PERIPHERAL, + .selector = 2, + .index = 1, + .size = 1, + .flags = UVC_CTRL_FLAG_GET_DEF + | UVC_CTRL_FLAG_GET_MAX + | UVC_CTRL_FLAG_GET_MIN + | UVC_CTRL_FLAG_GET_RES + | UVC_CTRL_FLAG_SET_CUR, + }, }; static const u32 uvc_control_classes[] = { @@ -1009,6 +1102,87 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .menu_mask = BIT(V4L2_COLORFX_VIVID) | BIT(V4L2_COLORFX_NONE), }, + { + .id = V4L2_CID_PAN_RELATIVE, + .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector = 1, + .size = 16, + .offset = 0, + .v4l2_type = V4L2_CTRL_TYPE_INTEGER, + .data_type = UVC_CTRL_DATA_TYPE_SIGNED, + }, + { + .id = V4L2_CID_TILT_RELATIVE, + .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector = 1, + .size = 16, + .offset = 16, + .v4l2_type = V4L2_CTRL_TYPE_INTEGER, + .data_type = UVC_CTRL_DATA_TYPE_SIGNED, + }, + { + .id = V4L2_CID_PAN_RESET, + .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector = 2, + .size = 1, + .offset = 0, + .v4l2_type = V4L2_CTRL_TYPE_BUTTON, + .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, + }, + { + .id = V4L2_CID_TILT_RESET, + .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector = 2, + .size = 1, + .offset = 1, + .v4l2_type = V4L2_CTRL_TYPE_BUTTON, + .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, + }, + { + .id = V4L2_CID_PAN_RELATIVE, + .entity = UVC_GUID_LOGITECH_PERIPHERAL, + .selector = 1, + .size = 16, + .offset = 0, + .v4l2_type = V4L2_CTRL_TYPE_INTEGER, + .data_type = UVC_CTRL_DATA_TYPE_SIGNED, + }, + { + .id = V4L2_CID_TILT_RELATIVE, + .entity = UVC_GUID_LOGITECH_PERIPHERAL, + .selector = 1, + .size = 16, + .offset = 16, + .v4l2_type = V4L2_CTRL_TYPE_INTEGER, + .data_type = UVC_CTRL_DATA_TYPE_SIGNED, + }, + { + .id = V4L2_CID_PAN_RESET, + .entity = UVC_GUID_LOGITECH_PERIPHERAL, + .selector = 2, + .size = 1, + .offset = 0, + .v4l2_type = V4L2_CTRL_TYPE_BUTTON, + .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, + }, + { + .id = V4L2_CID_TILT_RESET, + .entity = UVC_GUID_LOGITECH_PERIPHERAL, + .selector = 2, + .size = 1, + .offset = 1, + .v4l2_type = V4L2_CTRL_TYPE_BUTTON, + .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, + }, + { + .id = V4L2_CID_FOCUS_ABSOLUTE, + .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector = 3, + .size = 8, + .offset = 0, + .v4l2_type = V4L2_CTRL_TYPE_INTEGER, + .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, + }, }; /* ------------------------------------------------------------------------ diff --git a/include/linux/usb/uvc.h b/include/linux/usb/uvc.h index ea92ac623a45..dea23aabbad4 100644 --- a/include/linux/usb/uvc.h +++ b/include/linux/usb/uvc.h @@ -43,6 +43,12 @@ #define UVC_GUID_MSXU_1_5 \ {0xdc, 0x95, 0x3f, 0x0f, 0x32, 0x26, 0x4e, 0x4c, \ 0x92, 0xc9, 0xa0, 0x47, 0x82, 0xf4, 0x3b, 0xc8} +#define UVC_GUID_LOGITECH_MOTOR_CONTROL_V1 \ + {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \ + 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x56 } +#define UVC_GUID_LOGITECH_PERIPHERAL \ + {0x21, 0x2d, 0xe5, 0xff, 0x30, 0x80, 0x2c, 0x4e, \ + 0x82, 0xd9, 0xf5, 0x87, 0xd0, 0x05, 0x40, 0xbd } /* https://learn.microsoft.com/en-us/windows-hardware/drivers/stream/uvc-extensions-1-5#222-extension-unit-controls */ #define UVC_MSXU_CONTROL_FOCUS 0x01 -- 2.53.0.851.ga537e3e6e9-goog ^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 2/4] media: uvcvideo: Announce deprecation intentions for UVCIOC_CTRL_MAP 2026-03-16 13:34 [PATCH v3 0/4] media: uvcvideo: Map known XU controls Ricardo Ribalda 2026-03-16 13:34 ` [PATCH v3 1/4] media: uvcvideo: Import standard controls from uvcdynctrl Ricardo Ribalda @ 2026-03-16 13:34 ` Ricardo Ribalda 2026-03-16 13:34 ` [PATCH v3 3/4] media: uvcvideo: Introduce allow_privacy_override module parameter Ricardo Ribalda 2026-03-16 13:34 ` [PATCH v3 4/4] media: uvcvideo: RFC: Convert allow_privacy_override into Kconfig Ricardo Ribalda 3 siblings, 0 replies; 15+ messages in thread From: Ricardo Ribalda @ 2026-03-16 13:34 UTC (permalink / raw) To: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman Cc: linux-media, linux-kernel, linux-usb, Ricardo Ribalda The UVCIOC_CTRL_MAP lets userspace create a mapping for a custom control. This mapping is usually created by the uvcdynctrl userspace utility. We would like to get the mappings into the driver instead. Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> --- Documentation/userspace-api/media/drivers/uvcvideo.rst | 2 ++ drivers/media/usb/uvc/uvc_v4l2.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/Documentation/userspace-api/media/drivers/uvcvideo.rst b/Documentation/userspace-api/media/drivers/uvcvideo.rst index dbb30ad389ae..b09d2f8ba66e 100644 --- a/Documentation/userspace-api/media/drivers/uvcvideo.rst +++ b/Documentation/userspace-api/media/drivers/uvcvideo.rst @@ -109,6 +109,8 @@ IOCTL reference UVCIOC_CTRL_MAP - Map a UVC control to a V4L2 control ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**This IOCTL is deprecated and will be eventually removed** + Argument: struct uvc_xu_control_mapping **Description**: diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index d5860661c115..f9049e9c0d3a 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -1046,6 +1046,8 @@ static long uvc_ioctl_default(struct file *file, void *priv, bool valid_prio, switch (cmd) { /* Dynamic controls. */ case UVCIOC_CTRL_MAP: + pr_warn_once("uvcvideo: " DEPRECATED + "UVCIOC_CTRL_MAP ioctl will be eventually removed.\n"); return uvc_ioctl_xu_ctrl_map(chain, arg); case UVCIOC_CTRL_QUERY: @@ -1160,6 +1162,8 @@ static long uvc_v4l2_compat_ioctl32(struct file *file, switch (cmd) { case UVCIOC_CTRL_MAP32: + pr_warn_once("uvcvideo: " DEPRECATED + "UVCIOC_CTRL_MAP32 ioctl will be eventually removed.\n"); ret = uvc_v4l2_get_xu_mapping(&karg.xmap, up); if (ret) break; -- 2.53.0.851.ga537e3e6e9-goog ^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 3/4] media: uvcvideo: Introduce allow_privacy_override module parameter 2026-03-16 13:34 [PATCH v3 0/4] media: uvcvideo: Map known XU controls Ricardo Ribalda 2026-03-16 13:34 ` [PATCH v3 1/4] media: uvcvideo: Import standard controls from uvcdynctrl Ricardo Ribalda 2026-03-16 13:34 ` [PATCH v3 2/4] media: uvcvideo: Announce deprecation intentions for UVCIOC_CTRL_MAP Ricardo Ribalda @ 2026-03-16 13:34 ` Ricardo Ribalda 2026-03-19 0:36 ` Michal Pecio 2026-03-16 13:34 ` [PATCH v3 4/4] media: uvcvideo: RFC: Convert allow_privacy_override into Kconfig Ricardo Ribalda 3 siblings, 1 reply; 15+ messages in thread From: Ricardo Ribalda @ 2026-03-16 13:34 UTC (permalink / raw) To: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman Cc: linux-media, linux-kernel, linux-usb, Ricardo Ribalda Some camera modules have XU controls that can configure the behaviour of the privacy LED. Block mapping of those controls, unless the module is configured with a new parameter: allow_privacy_override. This is just an interim solution. Based on the users feedback, we will either put the privacy controls behind a CONFIG option, or completely block them. Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> --- drivers/media/usb/uvc/uvc_ctrl.c | 38 ++++++++++++++++++++++++++++++++++++++ drivers/media/usb/uvc/uvc_driver.c | 20 ++++++++++++++++++++ drivers/media/usb/uvc/uvc_v4l2.c | 7 +++++++ drivers/media/usb/uvc/uvcvideo.h | 2 ++ include/linux/usb/uvc.h | 4 ++++ 5 files changed, 71 insertions(+) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index b6e020b41671..3ca108b83f1d 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -3001,6 +3001,35 @@ static int uvc_ctrl_init_xu_ctrl(struct uvc_device *dev, return ret; } +bool uvc_ctrl_is_privacy_control(u8 entity[16], u8 selector) +{ + /* + * This list is not exhaustive, it is a best effort to block access to + * non documented controls that can affect user's privacy. + */ + struct privacy_control { + u8 entity[16]; + u8 selector; + } privacy_control[] = { + { + .entity = UVC_GUID_LOGITECH_USER_HW_CONTROL_V1, + .selector = 1, + }, + { + .entity = UVC_GUID_LOGITECH_PERIPHERAL, + .selector = 9, + }, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(privacy_control); i++) + if (!memcmp(entity, privacy_control[i].entity, 16) && + selector == privacy_control[i].selector) + return true; + + return false; +} + int uvc_xu_ctrl_query(struct uvc_video_chain *chain, struct uvc_xu_control_query *xqry) { @@ -3045,6 +3074,15 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain, return -ENOENT; } + if (uvc_ctrl_is_privacy_control(entity->guid, xqry->selector) && + !uvc_allow_privacy_override_param) { + dev_warn_once(&chain->dev->intf->dev, + "Privacy related controls can only be accessed if module parameter allow_privacy_override is true\n"); + uvc_dbg(chain->dev, CONTROL, "Blocking access to privacy related Control %pUl/%u\n", + entity->guid, xqry->selector); + return -EACCES; + } + if (mutex_lock_interruptible(&chain->ctrl_mutex)) return -ERESTARTSYS; diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index b0ca81d924b6..74c9dea29d36 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -36,6 +36,7 @@ unsigned int uvc_no_drop_param = 1; static unsigned int uvc_quirks_param = -1; unsigned int uvc_dbg_param; unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT; +bool uvc_allow_privacy_override_param; static struct usb_driver uvc_driver; @@ -2505,6 +2506,25 @@ MODULE_PARM_DESC(trace, "Trace level bitmask"); module_param_named(timeout, uvc_timeout_param, uint, 0644); MODULE_PARM_DESC(timeout, "Streaming control requests timeout"); +static int param_set_privacy(const char *val, const struct kernel_param *kp) +{ + pr_warn_once("uvcvideo: " DEPRECATED + "allow_privacy_override parameter will be eventually removed.\n"); + return param_set_bool(val, kp); +} + +static const struct kernel_param_ops param_ops_privacy = { + .set = param_set_privacy, + .get = param_get_bool, +}; + +param_check_bool(allow_privacy_override, &uvc_allow_privacy_override_param); +module_param_cb(allow_privacy_override, ¶m_ops_privacy, + &uvc_allow_privacy_override_param, 0644); +__MODULE_PARM_TYPE(allow_privacy_override, "bool"); +MODULE_PARM_DESC(allow_privacy_override, + "Allow access to privacy related controls"); + /* ------------------------------------------------------------------------ * Driver initialization and cleanup */ diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index f9049e9c0d3a..6d4f027c8402 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -133,6 +133,13 @@ static int uvc_ioctl_xu_ctrl_map(struct uvc_video_chain *chain, return -EINVAL; } + if (uvc_ctrl_is_privacy_control(xmap->entity, xmap->selector) && + !uvc_allow_privacy_override_param) { + dev_warn_once(&chain->dev->intf->dev, + "Privacy related controls can only be mapped if module parameter allow_privacy_override is true\n"); + return -EACCES; + } + map = kzalloc_obj(*map); if (map == NULL) return -ENOMEM; diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 8480d65ecb85..362110d58ca3 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -664,6 +664,7 @@ extern unsigned int uvc_no_drop_param; extern unsigned int uvc_dbg_param; extern unsigned int uvc_timeout_param; extern unsigned int uvc_hw_timestamps_param; +extern bool uvc_allow_privacy_override_param; #define uvc_dbg(_dev, flag, fmt, ...) \ do { \ @@ -794,6 +795,7 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain, struct uvc_xu_control_query *xqry); void uvc_ctrl_cleanup_fh(struct uvc_fh *handle); +bool uvc_ctrl_is_privacy_control(u8 entity[16], u8 selector); /* Utility functions */ struct usb_host_endpoint *uvc_find_endpoint(struct usb_host_interface *alts, diff --git a/include/linux/usb/uvc.h b/include/linux/usb/uvc.h index dea23aabbad4..70c2a7d25236 100644 --- a/include/linux/usb/uvc.h +++ b/include/linux/usb/uvc.h @@ -49,6 +49,10 @@ #define UVC_GUID_LOGITECH_PERIPHERAL \ {0x21, 0x2d, 0xe5, 0xff, 0x30, 0x80, 0x2c, 0x4e, \ 0x82, 0xd9, 0xf5, 0x87, 0xd0, 0x05, 0x40, 0xbd } +#define UVC_GUID_LOGITECH_USER_HW_CONTROL_V1 \ + {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \ + 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x1f } + /* https://learn.microsoft.com/en-us/windows-hardware/drivers/stream/uvc-extensions-1-5#222-extension-unit-controls */ #define UVC_MSXU_CONTROL_FOCUS 0x01 -- 2.53.0.851.ga537e3e6e9-goog ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v3 3/4] media: uvcvideo: Introduce allow_privacy_override module parameter 2026-03-16 13:34 ` [PATCH v3 3/4] media: uvcvideo: Introduce allow_privacy_override module parameter Ricardo Ribalda @ 2026-03-19 0:36 ` Michal Pecio 2026-03-19 9:56 ` Ricardo Ribalda 0 siblings, 1 reply; 15+ messages in thread From: Michal Pecio @ 2026-03-19 0:36 UTC (permalink / raw) To: Ricardo Ribalda Cc: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman, linux-media, linux-kernel, linux-usb On Mon, 16 Mar 2026 13:34:46 +0000, Ricardo Ribalda wrote: > Some camera modules have XU controls that can configure the behaviour of > the privacy LED. > > Block mapping of those controls, unless the module is configured with > a new parameter: allow_privacy_override. > > This is just an interim solution. Based on the users feedback, we will > either put the privacy controls behind a CONFIG option, or completely > block them. What feedback do you expect to get? Users will one day see their setup broken. They will curse you and jump through the hoops you set up. Next year they will see their setup broken completely. They will curse again and wish you all pain, but *after* the fact. > Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> > --- > drivers/media/usb/uvc/uvc_ctrl.c | 38 ++++++++++++++++++++++++++++++++++++++ > drivers/media/usb/uvc/uvc_driver.c | 20 ++++++++++++++++++++ > drivers/media/usb/uvc/uvc_v4l2.c | 7 +++++++ > drivers/media/usb/uvc/uvcvideo.h | 2 ++ > include/linux/usb/uvc.h | 4 ++++ > 5 files changed, 71 insertions(+) This doesn't seem to cover libusb, VM guests and such. What's even the attack vector? It has to be full remote code execution. And it's just an LED, when you see it turn on somebody already has your mugshot, if you notice at all. And the mugshot isn't your worst worry. > > diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c > index b6e020b41671..3ca108b83f1d 100644 > --- a/drivers/media/usb/uvc/uvc_ctrl.c > +++ b/drivers/media/usb/uvc/uvc_ctrl.c > @@ -3001,6 +3001,35 @@ static int uvc_ctrl_init_xu_ctrl(struct uvc_device *dev, > return ret; > } > > +bool uvc_ctrl_is_privacy_control(u8 entity[16], u8 selector) > +{ > + /* > + * This list is not exhaustive, it is a best effort to block access to > + * non documented controls that can affect user's privacy. > + */ So it's not removal of some controversial feature, but 3KB of extra code in everybody's kernel (I just applied this patch) and a forever game of whack-a-mole with HW vendors? They will win... You will blacklist features found by legitimate users and shared on public forums, while hackers will keep their findings to themselves. Assuming that there are any who even care. > + struct privacy_control { > + u8 entity[16]; > + u8 selector; > + } privacy_control[] = { > + { > + .entity = UVC_GUID_LOGITECH_USER_HW_CONTROL_V1, > + .selector = 1, > + }, > + { > + .entity = UVC_GUID_LOGITECH_PERIPHERAL, > + .selector = 9, > + }, > + }; > + int i; > + > + for (i = 0; i < ARRAY_SIZE(privacy_control); i++) > + if (!memcmp(entity, privacy_control[i].entity, 16) && > + selector == privacy_control[i].selector) > + return true; > + > + return false; > +} > + > int uvc_xu_ctrl_query(struct uvc_video_chain *chain, > struct uvc_xu_control_query *xqry) > { > @@ -3045,6 +3074,15 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain, > return -ENOENT; > } > > + if (uvc_ctrl_is_privacy_control(entity->guid, xqry->selector) && > + !uvc_allow_privacy_override_param) { > + dev_warn_once(&chain->dev->intf->dev, > + "Privacy related controls can only be accessed if module parameter allow_privacy_override is true\n"); > + uvc_dbg(chain->dev, CONTROL, "Blocking access to privacy related Control %pUl/%u\n", > + entity->guid, xqry->selector); > + return -EACCES; > + } > + > if (mutex_lock_interruptible(&chain->ctrl_mutex)) > return -ERESTARTSYS; > > diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c > index b0ca81d924b6..74c9dea29d36 100644 > --- a/drivers/media/usb/uvc/uvc_driver.c > +++ b/drivers/media/usb/uvc/uvc_driver.c > @@ -36,6 +36,7 @@ unsigned int uvc_no_drop_param = 1; > static unsigned int uvc_quirks_param = -1; > unsigned int uvc_dbg_param; > unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT; > +bool uvc_allow_privacy_override_param; > > static struct usb_driver uvc_driver; > > @@ -2505,6 +2506,25 @@ MODULE_PARM_DESC(trace, "Trace level bitmask"); > module_param_named(timeout, uvc_timeout_param, uint, 0644); > MODULE_PARM_DESC(timeout, "Streaming control requests timeout"); > > +static int param_set_privacy(const char *val, const struct kernel_param *kp) > +{ > + pr_warn_once("uvcvideo: " DEPRECATED > + "allow_privacy_override parameter will be eventually removed.\n"); > + return param_set_bool(val, kp); > +} > + > +static const struct kernel_param_ops param_ops_privacy = { > + .set = param_set_privacy, > + .get = param_get_bool, > +}; > + > +param_check_bool(allow_privacy_override, &uvc_allow_privacy_override_param); > +module_param_cb(allow_privacy_override, ¶m_ops_privacy, > + &uvc_allow_privacy_override_param, 0644); > +__MODULE_PARM_TYPE(allow_privacy_override, "bool"); > +MODULE_PARM_DESC(allow_privacy_override, > + "Allow access to privacy related controls"); > + > /* ------------------------------------------------------------------------ > * Driver initialization and cleanup > */ > diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c > index f9049e9c0d3a..6d4f027c8402 100644 > --- a/drivers/media/usb/uvc/uvc_v4l2.c > +++ b/drivers/media/usb/uvc/uvc_v4l2.c > @@ -133,6 +133,13 @@ static int uvc_ioctl_xu_ctrl_map(struct uvc_video_chain *chain, > return -EINVAL; > } > > + if (uvc_ctrl_is_privacy_control(xmap->entity, xmap->selector) && > + !uvc_allow_privacy_override_param) { > + dev_warn_once(&chain->dev->intf->dev, > + "Privacy related controls can only be mapped if module parameter allow_privacy_override is true\n"); > + return -EACCES; > + } > + > map = kzalloc_obj(*map); > if (map == NULL) > return -ENOMEM; > diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h > index 8480d65ecb85..362110d58ca3 100644 > --- a/drivers/media/usb/uvc/uvcvideo.h > +++ b/drivers/media/usb/uvc/uvcvideo.h > @@ -664,6 +664,7 @@ extern unsigned int uvc_no_drop_param; > extern unsigned int uvc_dbg_param; > extern unsigned int uvc_timeout_param; > extern unsigned int uvc_hw_timestamps_param; > +extern bool uvc_allow_privacy_override_param; > > #define uvc_dbg(_dev, flag, fmt, ...) \ > do { \ > @@ -794,6 +795,7 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain, > struct uvc_xu_control_query *xqry); > > void uvc_ctrl_cleanup_fh(struct uvc_fh *handle); > +bool uvc_ctrl_is_privacy_control(u8 entity[16], u8 selector); > > /* Utility functions */ > struct usb_host_endpoint *uvc_find_endpoint(struct usb_host_interface *alts, > diff --git a/include/linux/usb/uvc.h b/include/linux/usb/uvc.h > index dea23aabbad4..70c2a7d25236 100644 > --- a/include/linux/usb/uvc.h > +++ b/include/linux/usb/uvc.h > @@ -49,6 +49,10 @@ > #define UVC_GUID_LOGITECH_PERIPHERAL \ > {0x21, 0x2d, 0xe5, 0xff, 0x30, 0x80, 0x2c, 0x4e, \ > 0x82, 0xd9, 0xf5, 0x87, 0xd0, 0x05, 0x40, 0xbd } > +#define UVC_GUID_LOGITECH_USER_HW_CONTROL_V1 \ > + {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \ > + 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x1f } > + > > /* https://learn.microsoft.com/en-us/windows-hardware/drivers/stream/uvc-extensions-1-5#222-extension-unit-controls */ > #define UVC_MSXU_CONTROL_FOCUS 0x01 > > -- > 2.53.0.851.ga537e3e6e9-goog > ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 3/4] media: uvcvideo: Introduce allow_privacy_override module parameter 2026-03-19 0:36 ` Michal Pecio @ 2026-03-19 9:56 ` Ricardo Ribalda 2026-03-19 11:08 ` Michal Pecio 0 siblings, 1 reply; 15+ messages in thread From: Ricardo Ribalda @ 2026-03-19 9:56 UTC (permalink / raw) To: Michal Pecio Cc: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman, linux-media, linux-kernel, linux-usb Hi Michal On Thu, 19 Mar 2026 at 01:37, Michal Pecio <michal.pecio@gmail.com> wrote: > > On Mon, 16 Mar 2026 13:34:46 +0000, Ricardo Ribalda wrote: > > Some camera modules have XU controls that can configure the behaviour of > > the privacy LED. > > > > Block mapping of those controls, unless the module is configured with > > a new parameter: allow_privacy_override. > > > > This is just an interim solution. Based on the users feedback, we will > > either put the privacy controls behind a CONFIG option, or completely > > block them. > > What feedback do you expect to get? I want to identify the valid usecases for overriding the privacy LEDs. > > Users will one day see their setup broken. > They will curse you and jump through the hoops you set up. > Next year they will see their setup broken completely. > They will curse again and wish you all pain, but *after* the fact. The goal of the deprecation period is exactly this: to trigger a conversation before a permanent block. If a user relies on this, they can report it now. We can then decide if we need a specialized API for their use case or a Kconfig option, rather than leaving the current "anyone can turn off the privacy LED" status quo. > > > Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> > > --- > > drivers/media/usb/uvc/uvc_ctrl.c | 38 ++++++++++++++++++++++++++++++++++++++ > > drivers/media/usb/uvc/uvc_driver.c | 20 ++++++++++++++++++++ > > drivers/media/usb/uvc/uvc_v4l2.c | 7 +++++++ > > drivers/media/usb/uvc/uvcvideo.h | 2 ++ > > include/linux/usb/uvc.h | 4 ++++ > > 5 files changed, 71 insertions(+) > > This doesn't seem to cover libusb, VM guests and such. For libusb and VM guests to work you need to unbind the uvc driver. Only privileged users can do that. Today, any user with camera access can disable the privacy LED. > > What's even the attack vector? It has to be full remote code execution. > And it's just an LED, when you see it turn on somebody already has your > mugshot, if you notice at all. And the mugshot isn't your worst worry. The attack vector is that an app with camera access, like your browser, can record you when you don't want to be recorded. The LED will be a signal that something is happening. Imagine that you install a Flatpak for live streaming. Assuming the Flatpak is properly sandboxed, remote code execution is less worrisome than the app spying on you. > > > > > diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c > > index b6e020b41671..3ca108b83f1d 100644 > > --- a/drivers/media/usb/uvc/uvc_ctrl.c > > +++ b/drivers/media/usb/uvc/uvc_ctrl.c > > @@ -3001,6 +3001,35 @@ static int uvc_ctrl_init_xu_ctrl(struct uvc_device *dev, > > return ret; > > } > > > > +bool uvc_ctrl_is_privacy_control(u8 entity[16], u8 selector) > > +{ > > + /* > > + * This list is not exhaustive, it is a best effort to block access to > > + * non documented controls that can affect user's privacy. > > + */ > > So it's not removal of some controversial feature, but 3KB of extra > code in everybody's kernel (I just applied this patch) and a forever > game of whack-a-mole with HW vendors? They will win... Maybe I meassured it wrong. But I can only account for 1.3 KiB $ size drivers/media/usb/uvc/uvcvideo-without.ko text data bss dec hex filename 115974 3748 88 119810 1d402 drivers/media/usb/uvc/uvcvideo.ko $ size drivers/media/usb/uvc/uvcvideo-with.ko text data bss dec hex filename 117315 3767 88 121170 1d952 drivers/media/usb/uvc/uvcvideo.ko I see no need for vendors to hide these features, they simply added them because an OEM thought it was a nice feature to have, or because they left them as hardware debug features. > > You will blacklist features found by legitimate users and shared on > public forums, while hackers will keep their findings to themselves. > Assuming that there are any who even care. If a legitimate user needs a feature, this patch gives them a way to keep using it (allow_privacy_override) while notifying us. This allows the community to find a better, safer way to support that specific need without leaving the door wide open for everyone else. > > > + struct privacy_control { > > + u8 entity[16]; > > + u8 selector; > > + } privacy_control[] = { > > + { > > + .entity = UVC_GUID_LOGITECH_USER_HW_CONTROL_V1, > > + .selector = 1, > > + }, > > + { > > + .entity = UVC_GUID_LOGITECH_PERIPHERAL, > > + .selector = 9, > > + }, > > + }; > > + int i; > > + > > + for (i = 0; i < ARRAY_SIZE(privacy_control); i++) > > + if (!memcmp(entity, privacy_control[i].entity, 16) && > > + selector == privacy_control[i].selector) > > + return true; > > + > > + return false; > > +} > > + > > int uvc_xu_ctrl_query(struct uvc_video_chain *chain, > > struct uvc_xu_control_query *xqry) > > { > > @@ -3045,6 +3074,15 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain, > > return -ENOENT; > > } > > > > + if (uvc_ctrl_is_privacy_control(entity->guid, xqry->selector) && > > + !uvc_allow_privacy_override_param) { > > + dev_warn_once(&chain->dev->intf->dev, > > + "Privacy related controls can only be accessed if module parameter allow_privacy_override is true\n"); > > + uvc_dbg(chain->dev, CONTROL, "Blocking access to privacy related Control %pUl/%u\n", > > + entity->guid, xqry->selector); > > + return -EACCES; > > + } > > + > > if (mutex_lock_interruptible(&chain->ctrl_mutex)) > > return -ERESTARTSYS; > > > > diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c > > index b0ca81d924b6..74c9dea29d36 100644 > > --- a/drivers/media/usb/uvc/uvc_driver.c > > +++ b/drivers/media/usb/uvc/uvc_driver.c > > @@ -36,6 +36,7 @@ unsigned int uvc_no_drop_param = 1; > > static unsigned int uvc_quirks_param = -1; > > unsigned int uvc_dbg_param; > > unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT; > > +bool uvc_allow_privacy_override_param; > > > > static struct usb_driver uvc_driver; > > > > @@ -2505,6 +2506,25 @@ MODULE_PARM_DESC(trace, "Trace level bitmask"); > > module_param_named(timeout, uvc_timeout_param, uint, 0644); > > MODULE_PARM_DESC(timeout, "Streaming control requests timeout"); > > > > +static int param_set_privacy(const char *val, const struct kernel_param *kp) > > +{ > > + pr_warn_once("uvcvideo: " DEPRECATED > > + "allow_privacy_override parameter will be eventually removed.\n"); > > + return param_set_bool(val, kp); > > +} > > + > > +static const struct kernel_param_ops param_ops_privacy = { > > + .set = param_set_privacy, > > + .get = param_get_bool, > > +}; > > + > > +param_check_bool(allow_privacy_override, &uvc_allow_privacy_override_param); > > +module_param_cb(allow_privacy_override, ¶m_ops_privacy, > > + &uvc_allow_privacy_override_param, 0644); > > +__MODULE_PARM_TYPE(allow_privacy_override, "bool"); > > +MODULE_PARM_DESC(allow_privacy_override, > > + "Allow access to privacy related controls"); > > + > > /* ------------------------------------------------------------------------ > > * Driver initialization and cleanup > > */ > > diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c > > index f9049e9c0d3a..6d4f027c8402 100644 > > --- a/drivers/media/usb/uvc/uvc_v4l2.c > > +++ b/drivers/media/usb/uvc/uvc_v4l2.c > > @@ -133,6 +133,13 @@ static int uvc_ioctl_xu_ctrl_map(struct uvc_video_chain *chain, > > return -EINVAL; > > } > > > > + if (uvc_ctrl_is_privacy_control(xmap->entity, xmap->selector) && > > + !uvc_allow_privacy_override_param) { > > + dev_warn_once(&chain->dev->intf->dev, > > + "Privacy related controls can only be mapped if module parameter allow_privacy_override is true\n"); > > + return -EACCES; > > + } > > + > > map = kzalloc_obj(*map); > > if (map == NULL) > > return -ENOMEM; > > diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h > > index 8480d65ecb85..362110d58ca3 100644 > > --- a/drivers/media/usb/uvc/uvcvideo.h > > +++ b/drivers/media/usb/uvc/uvcvideo.h > > @@ -664,6 +664,7 @@ extern unsigned int uvc_no_drop_param; > > extern unsigned int uvc_dbg_param; > > extern unsigned int uvc_timeout_param; > > extern unsigned int uvc_hw_timestamps_param; > > +extern bool uvc_allow_privacy_override_param; > > > > #define uvc_dbg(_dev, flag, fmt, ...) \ > > do { \ > > @@ -794,6 +795,7 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain, > > struct uvc_xu_control_query *xqry); > > > > void uvc_ctrl_cleanup_fh(struct uvc_fh *handle); > > +bool uvc_ctrl_is_privacy_control(u8 entity[16], u8 selector); > > > > /* Utility functions */ > > struct usb_host_endpoint *uvc_find_endpoint(struct usb_host_interface *alts, > > diff --git a/include/linux/usb/uvc.h b/include/linux/usb/uvc.h > > index dea23aabbad4..70c2a7d25236 100644 > > --- a/include/linux/usb/uvc.h > > +++ b/include/linux/usb/uvc.h > > @@ -49,6 +49,10 @@ > > #define UVC_GUID_LOGITECH_PERIPHERAL \ > > {0x21, 0x2d, 0xe5, 0xff, 0x30, 0x80, 0x2c, 0x4e, \ > > 0x82, 0xd9, 0xf5, 0x87, 0xd0, 0x05, 0x40, 0xbd } > > +#define UVC_GUID_LOGITECH_USER_HW_CONTROL_V1 \ > > + {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \ > > + 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x1f } > > + > > > > /* https://learn.microsoft.com/en-us/windows-hardware/drivers/stream/uvc-extensions-1-5#222-extension-unit-controls */ > > #define UVC_MSXU_CONTROL_FOCUS 0x01 > > > > -- > > 2.53.0.851.ga537e3e6e9-goog > > -- Ricardo Ribalda ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 3/4] media: uvcvideo: Introduce allow_privacy_override module parameter 2026-03-19 9:56 ` Ricardo Ribalda @ 2026-03-19 11:08 ` Michal Pecio 2026-03-19 11:43 ` Ricardo Ribalda 0 siblings, 1 reply; 15+ messages in thread From: Michal Pecio @ 2026-03-19 11:08 UTC (permalink / raw) To: Ricardo Ribalda Cc: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman, linux-media, linux-kernel, linux-usb On Thu, 19 Mar 2026 10:56:59 +0100, Ricardo Ribalda wrote: > The goal of the deprecation period is exactly this: to trigger a > conversation before a permanent block. Most users will just curse and edit their /etc/modprobe.conf. They may post a rant on some distro forum. I suspect no one will monitor this. > We can then decide if we need a specialized API for their use case or > a Kconfig option, rather than leaving the current "anyone can turn > off the privacy LED" status quo. Why not just add the specialized API right away? I believe users affected by this regression are already known, ISTR some negative response to previous iterations of this patch. Kconfig option sounds crazy, who would want to rebuild the kernel for this? Depending on BROKEN is double crazy. > The attack vector is that an app with camera access, like your > browser, can record you when you don't want to be recorded. > The LED will be a signal that something is happening. > > Imagine that you install a Flatpak for live streaming. Assuming the > Flatpak is properly sandboxed, remote code execution is less worrisome > than the app spying on you. Theoretically yes. But also nobody should rely on those LEDs. People who care ask HW vendors for physical switches or disconnect the camera while not in use. I have seen black tape on laptop lids. Are there more owners of affected hardware who want this code than those who don't? Maybe it could be a Kconfig option for them :) Most of my USB cameras don't even have activity LEDs. > > So it's not removal of some controversial feature, but 3KB of extra > > code in everybody's kernel (I just applied this patch) and a forever > > game of whack-a-mole with HW vendors? They will win... > > Maybe I meassured it wrong. But I can only account for 1.3 KiB I simply ran stat uvcvideo.ko and calculated difference. Could be a matter of different kernel configs. > I see no need for vendors to hide these features, they simply added > them because an OEM thought it was a nice feature to have, or because > they left them as hardware debug features. But how will the kernel know about those random debug backdoors? It just seems that whatever is discovered by users and becomes popular enough to reach linux-media, will be getting blacklisted and broken. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 3/4] media: uvcvideo: Introduce allow_privacy_override module parameter 2026-03-19 11:08 ` Michal Pecio @ 2026-03-19 11:43 ` Ricardo Ribalda 2026-03-24 12:07 ` Michal Pecio 0 siblings, 1 reply; 15+ messages in thread From: Ricardo Ribalda @ 2026-03-19 11:43 UTC (permalink / raw) To: Michal Pecio Cc: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman, linux-media, linux-kernel, linux-usb Hi Michal On Thu, 19 Mar 2026 at 12:09, Michal Pecio <michal.pecio@gmail.com> wrote: > > On Thu, 19 Mar 2026 10:56:59 +0100, Ricardo Ribalda wrote: > > The goal of the deprecation period is exactly this: to trigger a > > conversation before a permanent block. > > Most users will just curse and edit their /etc/modprobe.conf. They may > post a rant on some distro forum. I suspect no one will monitor this. > > > We can then decide if we need a specialized API for their use case or > > a Kconfig option, rather than leaving the current "anyone can turn > > off the privacy LED" status quo. > > Why not just add the specialized API right away? We don't know the exact use cases yet, and I do not want to design an API without understanding the users for it. At this moment, we have only identified these usecases: - Disabling the LED to avoid reflections in glasses. (This is generally a non-issue with modern hardware). - Baby monitors. (I would argue that physical tape is the correct solution for a sleep-disturbing light). > > I believe users affected by this regression are already known, > ISTR some negative response to previous iterations of this patch. > > Kconfig option sounds crazy, who would want to rebuild the kernel > for this? Depending on BROKEN is double crazy. I am not set on the final implementation yet; it is exactly the kind of topic we should discuss at a media summit. > > > The attack vector is that an app with camera access, like your > > browser, can record you when you don't want to be recorded. > > The LED will be a signal that something is happening. > > > > Imagine that you install a Flatpak for live streaming. Assuming the > > Flatpak is properly sandboxed, remote code execution is less worrisome > > than the app spying on you. > > Theoretically yes. But also nobody should rely on those LEDs. > People who care ask HW vendors for physical switches or disconnect > the camera while not in use. I have seen black tape on laptop lids. I rely on my LEDs. I know they are wired to the sensor power supply, so the LED is definitely on when the camera is in use. I want all users to be able to trust their LEDs like I do. > > Are there more owners of affected hardware who want this code than > those who don't? Maybe it could be a Kconfig option for them :) I believe the majority of users prefer a system that is "secure by default." Most people expect that if the LED is off, the camera is off. > > Most of my USB cameras don't even have activity LEDs. > > > > So it's not removal of some controversial feature, but 3KB of extra > > > code in everybody's kernel (I just applied this patch) and a forever > > > game of whack-a-mole with HW vendors? They will win... > > > > Maybe I meassured it wrong. But I can only account for 1.3 KiB > > I simply ran stat uvcvideo.ko and calculated difference. > Could be a matter of different kernel configs. > > > I see no need for vendors to hide these features, they simply added > > them because an OEM thought it was a nice feature to have, or because > > they left them as hardware debug features. > > But how will the kernel know about those random debug backdoors? > It just seems that whatever is discovered by users and becomes popular > enough to reach linux-media, will be getting blacklisted and broken. > I prefer to say "filtered" rather than "broken." It’s a matter of perspective: we are filtering out non-standard controls that undermine user privacy. While we might not catch every debug backdoor immediately, setting a policy and blocking known overrides is a significant step and also sends a strong message to vendors. Best regards! -- Ricardo Ribalda ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 3/4] media: uvcvideo: Introduce allow_privacy_override module parameter 2026-03-19 11:43 ` Ricardo Ribalda @ 2026-03-24 12:07 ` Michal Pecio 2026-03-26 11:55 ` Ricardo Ribalda 0 siblings, 1 reply; 15+ messages in thread From: Michal Pecio @ 2026-03-24 12:07 UTC (permalink / raw) To: Ricardo Ribalda Cc: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman, linux-media, linux-kernel, linux-usb On Thu, 19 Mar 2026 12:43:21 +0100, Ricardo Ribalda wrote: > > > We can then decide if we need a specialized API for their use > > > case or a Kconfig option, rather than leaving the current "anyone > > > can turn off the privacy LED" status quo. > > > > Why not just add the specialized API right away? > > We don't know the exact use cases yet, and I do not want to design > an API without understanding the users for it. > > At this moment, we have only identified these usecases: > > - Disabling the LED to avoid reflections in glasses. (This is > generally a non-issue with modern hardware). > - Baby monitors. (I would argue that physical tape is the correct > solution for a sleep-disturbing light). Indeed it was a rhetorical question, I suspect this won't go anywhere beyond the module parameter for lack of interest from users. Apparently it's a niche thing and it already works well enough for those who care. Kconfig could make more sense to exclude this whole "filtering" logic for those who don't care and may not appreciate bloat, e.g. embedded. > I rely on my LEDs. I know they are wired to the sensor power supply, > so the LED is definitely on when the camera is in use. > I want all users to be able to trust their LEDs like I do. This is objectively impossible without a soldering iron, and trust in something that's not even real is ralely a good thing. Ultimately it's just a software controllable LED. Anyone can drive it through USBFS. You have a point that restricting this in uvcvideo may keep some sandboxed applications on some HW from behaving in a manner unexpected by some users, but that's about the limit of it. And I wish that you enjoyed the same flexibility as those Logitech camera owners. But you wouldn't want me to try make it happen ;) Regards, Michal ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 3/4] media: uvcvideo: Introduce allow_privacy_override module parameter 2026-03-24 12:07 ` Michal Pecio @ 2026-03-26 11:55 ` Ricardo Ribalda 0 siblings, 0 replies; 15+ messages in thread From: Ricardo Ribalda @ 2026-03-26 11:55 UTC (permalink / raw) To: Michal Pecio Cc: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman, linux-media, linux-kernel, linux-usb Hi Michal On Tue, 24 Mar 2026 at 13:07, Michal Pecio <michal.pecio@gmail.com> wrote: > > On Thu, 19 Mar 2026 12:43:21 +0100, Ricardo Ribalda wrote: > > > > We can then decide if we need a specialized API for their use > > > > case or a Kconfig option, rather than leaving the current "anyone > > > > can turn off the privacy LED" status quo. > > > > > > Why not just add the specialized API right away? > > > > We don't know the exact use cases yet, and I do not want to design > > an API without understanding the users for it. > > > > At this moment, we have only identified these usecases: > > > > - Disabling the LED to avoid reflections in glasses. (This is > > generally a non-issue with modern hardware). > > - Baby monitors. (I would argue that physical tape is the correct > > solution for a sleep-disturbing light). > > Indeed it was a rhetorical question, I suspect this won't go anywhere > beyond the module parameter for lack of interest from users. Apparently > it's a niche thing and it already works well enough for those who care. > > Kconfig could make more sense to exclude this whole "filtering" logic > for those who don't care and may not appreciate bloat, e.g. embedded. > > > I rely on my LEDs. I know they are wired to the sensor power supply, > > so the LED is definitely on when the camera is in use. > > I want all users to be able to trust their LEDs like I do. > > This is objectively impossible without a soldering iron, and trust in > something that's not even real is ralely a good thing. > > Ultimately it's just a software controllable LED. Anyone can drive it > through USBFS. You have a point that restricting this in uvcvideo may > keep some sandboxed applications on some HW from behaving in a manner > unexpected by some users, but that's about the limit of it. Just one clarification. Not every user has permission to unbind the uvcdriver and use ubsfs. Only priviledged users can do that. From my point of view it is similar to the filesystem. "Anyone" can read/write files (if they have permission) but just priviledge users can `dd of=/dev/sda` > > And I wish that you enjoyed the same flexibility as those Logitech > camera owners. But you wouldn't want me to try make it happen ;) > > Regards, > Michal -- Ricardo Ribalda ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v3 4/4] media: uvcvideo: RFC: Convert allow_privacy_override into Kconfig 2026-03-16 13:34 [PATCH v3 0/4] media: uvcvideo: Map known XU controls Ricardo Ribalda ` (2 preceding siblings ...) 2026-03-16 13:34 ` [PATCH v3 3/4] media: uvcvideo: Introduce allow_privacy_override module parameter Ricardo Ribalda @ 2026-03-16 13:34 ` Ricardo Ribalda 2026-03-18 14:16 ` Greg Kroah-Hartman 3 siblings, 1 reply; 15+ messages in thread From: Ricardo Ribalda @ 2026-03-16 13:34 UTC (permalink / raw) To: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman Cc: linux-media, linux-kernel, linux-usb, Ricardo Ribalda This patch is just shared for discussion purposes! Do not land. In a perfect world, after a deprecation process, we will be able to remove allow_privacy_override and block all privacy related controls. If there is any usecase out in the field that resists, we shall move it into a Kconfig. This patch shows how the transition to Kconfig can look. Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> --- drivers/media/usb/uvc/Kconfig | 11 +++++++++++ drivers/media/usb/uvc/uvc_ctrl.c | 4 ++-- drivers/media/usb/uvc/uvc_driver.c | 20 -------------------- drivers/media/usb/uvc/uvc_v4l2.c | 4 ++-- drivers/media/usb/uvc/uvcvideo.h | 1 - 5 files changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/media/usb/uvc/Kconfig b/drivers/media/usb/uvc/Kconfig index 579532272fd6..7c0f2260d135 100644 --- a/drivers/media/usb/uvc/Kconfig +++ b/drivers/media/usb/uvc/Kconfig @@ -20,3 +20,14 @@ config USB_VIDEO_CLASS_INPUT_EVDEV to report button events. If you are in doubt, say Y. + +config USB_VIDEO_CLASS_ALLOW_PRIVACY_OVERRIDE + bool "Allow overriding the privacy controls" + default n + depends on USB_VIDEO_CLASS && BROKEN + help + If this option is enabled, the privacy related controls, such as + the ones controlling the privacy LED will be accessible from + userspace. + + If you are in doubt, say N. diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 3ca108b83f1d..c9c195974765 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -3075,9 +3075,9 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain, } if (uvc_ctrl_is_privacy_control(entity->guid, xqry->selector) && - !uvc_allow_privacy_override_param) { + !IS_ENABLED(CONFIG_USB_VIDEO_CLASS_ALLOW_PRIVACY_OVERRIDE)) { dev_warn_once(&chain->dev->intf->dev, - "Privacy related controls can only be accessed if module parameter allow_privacy_override is true\n"); + "Privacy related controls can only be accessed if CONFIG_USB_VIDEO_CLASS_ALLOW_PRIVACY_OVERRIDE is true\n"); uvc_dbg(chain->dev, CONTROL, "Blocking access to privacy related Control %pUl/%u\n", entity->guid, xqry->selector); return -EACCES; diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 74c9dea29d36..b0ca81d924b6 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -36,7 +36,6 @@ unsigned int uvc_no_drop_param = 1; static unsigned int uvc_quirks_param = -1; unsigned int uvc_dbg_param; unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT; -bool uvc_allow_privacy_override_param; static struct usb_driver uvc_driver; @@ -2506,25 +2505,6 @@ MODULE_PARM_DESC(trace, "Trace level bitmask"); module_param_named(timeout, uvc_timeout_param, uint, 0644); MODULE_PARM_DESC(timeout, "Streaming control requests timeout"); -static int param_set_privacy(const char *val, const struct kernel_param *kp) -{ - pr_warn_once("uvcvideo: " DEPRECATED - "allow_privacy_override parameter will be eventually removed.\n"); - return param_set_bool(val, kp); -} - -static const struct kernel_param_ops param_ops_privacy = { - .set = param_set_privacy, - .get = param_get_bool, -}; - -param_check_bool(allow_privacy_override, &uvc_allow_privacy_override_param); -module_param_cb(allow_privacy_override, ¶m_ops_privacy, - &uvc_allow_privacy_override_param, 0644); -__MODULE_PARM_TYPE(allow_privacy_override, "bool"); -MODULE_PARM_DESC(allow_privacy_override, - "Allow access to privacy related controls"); - /* ------------------------------------------------------------------------ * Driver initialization and cleanup */ diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index 6d4f027c8402..f83abbd13aca 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -134,9 +134,9 @@ static int uvc_ioctl_xu_ctrl_map(struct uvc_video_chain *chain, } if (uvc_ctrl_is_privacy_control(xmap->entity, xmap->selector) && - !uvc_allow_privacy_override_param) { + !IS_ENABLED(CONFIG_USB_VIDEO_CLASS_ALLOW_PRIVACY_OVERRIDE)) { dev_warn_once(&chain->dev->intf->dev, - "Privacy related controls can only be mapped if module parameter allow_privacy_override is true\n"); + "Privacy related controls can only be mapped if CONFIG_USB_VIDEO_CLASS_ALLOW_PRIVACY_OVERRIDE is true\n"); return -EACCES; } diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 362110d58ca3..2898384d5f78 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -664,7 +664,6 @@ extern unsigned int uvc_no_drop_param; extern unsigned int uvc_dbg_param; extern unsigned int uvc_timeout_param; extern unsigned int uvc_hw_timestamps_param; -extern bool uvc_allow_privacy_override_param; #define uvc_dbg(_dev, flag, fmt, ...) \ do { \ -- 2.53.0.851.ga537e3e6e9-goog ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v3 4/4] media: uvcvideo: RFC: Convert allow_privacy_override into Kconfig 2026-03-16 13:34 ` [PATCH v3 4/4] media: uvcvideo: RFC: Convert allow_privacy_override into Kconfig Ricardo Ribalda @ 2026-03-18 14:16 ` Greg Kroah-Hartman 2026-03-18 14:57 ` Ricardo Ribalda 0 siblings, 1 reply; 15+ messages in thread From: Greg Kroah-Hartman @ 2026-03-18 14:16 UTC (permalink / raw) To: Ricardo Ribalda Cc: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, linux-media, linux-kernel, linux-usb On Mon, Mar 16, 2026 at 01:34:47PM +0000, Ricardo Ribalda wrote: > This patch is just shared for discussion purposes! Do not land. > > In a perfect world, after a deprecation process, we will be able to > remove allow_privacy_override and block all privacy related controls. Why add something you are only going to remove in the future? What has changed to require this now, and will change in the future to make it not needed? > If there is any usecase out in the field that resists, we shall move it > into a Kconfig. What does this mean? How will anyone know to "resist"? > This patch shows how the transition to Kconfig can look. I'm confused as to what you want to do here... greg k-h ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 4/4] media: uvcvideo: RFC: Convert allow_privacy_override into Kconfig 2026-03-18 14:16 ` Greg Kroah-Hartman @ 2026-03-18 14:57 ` Ricardo Ribalda 2026-03-19 11:50 ` Gergo Koteles 0 siblings, 1 reply; 15+ messages in thread From: Ricardo Ribalda @ 2026-03-18 14:57 UTC (permalink / raw) To: Greg Kroah-Hartman Cc: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, linux-media, linux-kernel, linux-usb Hi Greg On Wed, 18 Mar 2026 at 15:17, Greg Kroah-Hartman <gregkh@linuxfoundation.org> wrote: > > On Mon, Mar 16, 2026 at 01:34:47PM +0000, Ricardo Ribalda wrote: > > This patch is just shared for discussion purposes! Do not land. > > > > In a perfect world, after a deprecation process, we will be able to > > remove allow_privacy_override and block all privacy related controls. > > Why add something you are only going to remove in the future? What has > changed to require this now, and will change in the future to make it > not needed? Currently, any application with camera access can manipulate the privacy LED. I believe this is a security flaw; ideally, the kernel should block all such controls by default. However, blocking these controls immediately might be seen as a regression for certain users. I added allow_privacy_override to: - Prevent breaking existing workflows immediately upon a kernel update. - Give users time to report why they still need manual LED control. The goal is to gather these use cases over the next 1–2 years. Once we understand the legitimate needs, we can either implement a proper specialized mechanism for them or move the toggle to a Kconfig option for those who explicitly need to opt-in to the old behavior or simply remove the toggle altogether. For the record, identified use cases so far: - Old hardware with red LEDs that reflect on glasses. (Likely a dying niche). - Using cameras as baby monitors where the LED disturbs sleep. (Arguably solvable with a piece of tape on the LED, but still a reported use case). > > > If there is any usecase out in the field that resists, we shall move it > > into a Kconfig. > > What does this mean? How will anyone know to "resist"? My phrasing was poor, sorry about that. What I mean is: if, after a deprecation period, we find there are still legitimate reasons to allow LED overrides, we will move the functionality behind a Kconfig option (e.g., USB_VIDEO_CLASS_ALLOW_PRIVACY_OVERRIDE) or other option. If no one reports a need for it, we simply remove the override capability entirely. > > > This patch shows how the transition to Kconfig can look. > > I'm confused as to what you want to do here... This patch is just a RFC to demonstrate the final state if we decide a Kconfig option is necessary. The actual plan is to land patches 1-3 first, wait for feedback, and only then decide if we need the Kconfig transition or a full removal or something else. > > greg k-h -- Ricardo Ribalda ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 4/4] media: uvcvideo: RFC: Convert allow_privacy_override into Kconfig 2026-03-18 14:57 ` Ricardo Ribalda @ 2026-03-19 11:50 ` Gergo Koteles 2026-03-19 12:06 ` Ricardo Ribalda 0 siblings, 1 reply; 15+ messages in thread From: Gergo Koteles @ 2026-03-19 11:50 UTC (permalink / raw) To: Ricardo Ribalda Cc: Greg Kroah-Hartman, Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, linux-media, linux-kernel, linux-usb Hi Ricardo, On Wed, 2026-03-18 at 15:57 +0100, Ricardo Ribalda wrote: > Hi Greg > > On Wed, 18 Mar 2026 at 15:17, Greg Kroah-Hartman > <gregkh@linuxfoundation.org> wrote: > > > > On Mon, Mar 16, 2026 at 01:34:47PM +0000, Ricardo Ribalda wrote: > > > This patch is just shared for discussion purposes! Do not land. > > > > > > In a perfect world, after a deprecation process, we will be able to > > > remove allow_privacy_override and block all privacy related controls. > > > > Why add something you are only going to remove in the future? What has > > changed to require this now, and will change in the future to make it > > not needed? > > Currently, any application with camera access can manipulate the > privacy LED. I believe this is a security flaw; ideally, the kernel > should block all such controls by default. > > However, blocking these controls immediately might be seen as a > regression for certain users. I added allow_privacy_override to: > - Prevent breaking existing workflows immediately upon a kernel update. > - Give users time to report why they still need manual LED control. > > The goal is to gather these use cases over the next 1–2 years. Once we > understand the legitimate needs, we can either implement a proper > specialized mechanism for them or move the toggle to a Kconfig option > for those who explicitly need to opt-in to the old behavior or simply > remove the toggle altogether. > > For the record, identified use cases so far: > - Old hardware with red LEDs that reflect on glasses. (Likely a dying niche). Older Logitech cameras, like the c920, have fairly large LEDs that can be reflective, and it's hard to cover them up aesthetically. Laurent wrote [1] that's why Logitech added this functionality a long time ago. You can find old Logitech software for Windows that still allows you to turn off the LEDs [2]. I tried it in a Win10 VM and it really works. The c920 is a very popular camera, still available in stores today. Amazon says it sells 12k of them per month [3]. 1: https://lore.kernel.org/all/20251119041907.GH10711@pendragon.ideasonboard.com/ 2: https://www.reddit.com/r/logitech/comments/v641x6/comment/nr22zo7/ 3: https://www.amazon.com/s?k=logitech+c920 > - Using cameras as baby monitors where the LED disturbs sleep. And pet cameras and surveillance cameras don't need LEDs either. > (Arguably solvable with a piece of tape on the LED, but still a > reported use case). > Furthermore, if we filter these two Logitech XUs, we could then add the similar XUs of the camera modules in laptops and this could be an ever- growing list. > Best regards, Gergo Koteles ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 4/4] media: uvcvideo: RFC: Convert allow_privacy_override into Kconfig 2026-03-19 11:50 ` Gergo Koteles @ 2026-03-19 12:06 ` Ricardo Ribalda 0 siblings, 0 replies; 15+ messages in thread From: Ricardo Ribalda @ 2026-03-19 12:06 UTC (permalink / raw) To: Gergo Koteles Cc: Greg Kroah-Hartman, Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, linux-media, linux-kernel, linux-usb Hi Gergo On Thu, 19 Mar 2026 at 12:50, Gergo Koteles <soyer@irl.hu> wrote: > > Hi Ricardo, > > On Wed, 2026-03-18 at 15:57 +0100, Ricardo Ribalda wrote: > > Hi Greg > > > > On Wed, 18 Mar 2026 at 15:17, Greg Kroah-Hartman > > <gregkh@linuxfoundation.org> wrote: > > > > > > On Mon, Mar 16, 2026 at 01:34:47PM +0000, Ricardo Ribalda wrote: > > > > This patch is just shared for discussion purposes! Do not land. > > > > > > > > In a perfect world, after a deprecation process, we will be able to > > > > remove allow_privacy_override and block all privacy related controls. > > > > > > Why add something you are only going to remove in the future? What has > > > changed to require this now, and will change in the future to make it > > > not needed? > > > > Currently, any application with camera access can manipulate the > > privacy LED. I believe this is a security flaw; ideally, the kernel > > should block all such controls by default. > > > > However, blocking these controls immediately might be seen as a > > regression for certain users. I added allow_privacy_override to: > > - Prevent breaking existing workflows immediately upon a kernel update. > > - Give users time to report why they still need manual LED control. > > > > The goal is to gather these use cases over the next 1–2 years. Once we > > understand the legitimate needs, we can either implement a proper > > specialized mechanism for them or move the toggle to a Kconfig option > > for those who explicitly need to opt-in to the old behavior or simply > > remove the toggle altogether. > > > > For the record, identified use cases so far: > > - Old hardware with red LEDs that reflect on glasses. (Likely a dying niche). > > Older Logitech cameras, like the c920, have fairly large LEDs that can > be reflective, and it's hard to cover them up aesthetically. Laurent > wrote [1] that's why Logitech added this functionality a long time ago. > > You can find old Logitech software for Windows that still allows you to > turn off the LEDs [2]. I tried it in a Win10 VM and it really works. In the same link you will find that Logitech has removed that option in newer version of the Logitech software and a "Official Logitech Representative" says that: ```Please be informed that there is no way to disable the blue led light on the webcam as that is the indicator that the webcam is active and its mainly for security purpose.``` Other users say that ```I would not buy a webcam with an led that can be switched off and that can watch me without any chance noticing it.``` This is definitely a requested feature by the users and it seems even the vendor has realized that the security risk of a "stealth" camera outweighs the benefit of turning off the LED. > > The c920 is a very popular camera, still available in stores today. > Amazon says it sells 12k of them per month [3]. > > 1: > https://lore.kernel.org/all/20251119041907.GH10711@pendragon.ideasonboard.com/ > > 2: https://www.reddit.com/r/logitech/comments/v641x6/comment/nr22zo7/ > > 3: https://www.amazon.com/s?k=logitech+c920 > > > - Using cameras as baby monitors where the LED disturbs sleep. > > And pet cameras and surveillance cameras don't need LEDs either. Agree. All surveillance cameras. All those special cases can use the allow_privacy_override parameter until we find a good way to handle their use case. > > > (Arguably solvable with a piece of tape on the LED, but still a > > reported use case). > > > > Furthermore, if we filter these two Logitech XUs, we could then add the > similar XUs of the camera modules in laptops and this could be an ever- > growing list. That is the goal, to have a list as comprehensive as possible. > > > > Best regards, > Gergo Koteles -- Ricardo Ribalda ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-03-26 11:55 UTC | newest] Thread overview: 15+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-03-16 13:34 [PATCH v3 0/4] media: uvcvideo: Map known XU controls Ricardo Ribalda 2026-03-16 13:34 ` [PATCH v3 1/4] media: uvcvideo: Import standard controls from uvcdynctrl Ricardo Ribalda 2026-03-16 13:34 ` [PATCH v3 2/4] media: uvcvideo: Announce deprecation intentions for UVCIOC_CTRL_MAP Ricardo Ribalda 2026-03-16 13:34 ` [PATCH v3 3/4] media: uvcvideo: Introduce allow_privacy_override module parameter Ricardo Ribalda 2026-03-19 0:36 ` Michal Pecio 2026-03-19 9:56 ` Ricardo Ribalda 2026-03-19 11:08 ` Michal Pecio 2026-03-19 11:43 ` Ricardo Ribalda 2026-03-24 12:07 ` Michal Pecio 2026-03-26 11:55 ` Ricardo Ribalda 2026-03-16 13:34 ` [PATCH v3 4/4] media: uvcvideo: RFC: Convert allow_privacy_override into Kconfig Ricardo Ribalda 2026-03-18 14:16 ` Greg Kroah-Hartman 2026-03-18 14:57 ` Ricardo Ribalda 2026-03-19 11:50 ` Gergo Koteles 2026-03-19 12:06 ` Ricardo Ribalda
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox