lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <CANiDSCsB2mEf2JGUTNgkrgYo8LYgSNyD126-Hq_Ek__O3KtxTQ@mail.gmail.com>
Date: Fri, 24 Oct 2025 13:04:05 +0200
From: Ricardo Ribalda <ribalda@...omium.org>
To: Laurent Pinchart <laurent.pinchart@...asonboard.com>
Cc: Hans de Goede <hansg@...nel.org>, Mauro Carvalho Chehab <mchehab@...nel.org>, linux-media@...r.kernel.org, 
	linux-kernel@...r.kernel.org
Subject: Re: [PATCH v2] media: uvcvideo: Create a specific id namespace for
 output entities

Hi Laurent

On Fri, 24 Oct 2025 at 12:50, Laurent Pinchart
<laurent.pinchart@...asonboard.com> wrote:
>
> On Wed, Oct 22, 2025 at 01:12:09PM +0000, Ricardo Ribalda wrote:
> > Nothing can be connected to an output terminal. Which means that no
> > other entity can reference an output terminal as baSourceId.
> >
> > Use this fact to move all the output streaming entities, which have no
> > controls, to a different namespace.
> >
> > The output entities are usually named after the dev_name() of the usb
> > device, so there should not be any uAPI change from this change.
> >
> > Although with this change we can handle some id collisions
> > automagically, change the logic of uvc_alloc_new_entity() to keep
> > showing a warning when a camera has invalid descriptors. Hopefully this
> > message will help vendors fix their invalid descriptors.
>
> This is one of the commits that I expect we'll go back to in the future
> when trying to remember why we namespace the streeaming terminal IDs.
> Let's make the rationale very clear, and also mention the name of the
> devices we know to be affected.
>
> ----
> Some devices, such as the Grandstream GUV3100 and the LSK Meeting Eye
> for Business & Home, exhibit entity ID collisions between units and
> streaming output terminals.
>
> The UVC specification requires unit and terminal IDs to be unique, and
> uses the ID to reference entities:
>
> - In control requests, to identify the target entity
> - In the UVC units and terminals descriptors' bSourceID field, to
>   identify source entities
> - In the UVC input header descriptor's bTerminalLink, to identify the
>   terminal associated with a streaming interface
>
> Entity ID collisions break accessing controls and make the graph
> description in the UVC descriptors ambiguous. However, collisions where
> one of the entities is a streaming output terminal and the other entity
> is not a streaming terminal are less severe. Streaming output terminals
> have no controls, and, as they are the final entity in pipelines, they
> are never referenced in descriptors as source entities. They are
> referenced by ID only from innput header descriptors, which by
> definition only reference streaming terminals.
>
> For these reasons, we can work around the collision by giving streaming
> output terminals their own ID namespace. Do so by setting bit
> UVC_TERM_OUTPUT (15) in the uvc_entity.id field, which is normally never
> set as the ID is a 8-bit value.
>
> This ID change doesn't affect the entity name in the media controller
> graph as the name isn't constructed from the ID, so there should not be
> any impact on the uAPI.
>
> Although this change handles some ID collisions automagically, keep
> printing an error in uvc_alloc_new_entity() when a camera has invalid
> descriptors. Hopefully this message will help vendors fix their invalid
> descriptors.
> ----
>
> >
> > Suggested-by: Laurent Pinchart <laurent.pinchart@...asonboard.com>
> > Signed-off-by: Ricardo Ribalda <ribalda@...omium.org>
> > ---
> > Hi, this patch fixes support for some devices with invalid USB
> > descriptor.
> >
> > It is orthogonal to:
> > https://lore.kernel.org/linux-media/20251021184213.GC19043@pendragon.ideasonboard.com/T/#t
> >
> > Some devices will be fixed by the other patch, other devices will be
> > fixed by this. In my opinion is worth to land both patches.
>
> I would prefer merging this fix only (or rather, if we merge the other
> one as a quick fix, reverting it once we merge this one). The rationale
> is that enabling non-compliant behaviour should be limited to issues we
> know about, otherwise it could encourage making more non-compliant
> devices.
>
> The UVC specification states
>
>   Each Unit and Terminal within the video function is assigned a unique
>   identification number, the Unit ID (UID) or Terminal ID (TID),
>   contained in the bUnitID or bTerminalID field of the descriptor. The
>   value 0x00 is reserved for undefined ID, effectively restricting the
>   total number of addressable entities in the video function (both Units
>   and Terminals) to 255.
>
> To me it's clear that the unit and terminal IDs share the same
> namespace, but I suppose some vendors can overlook that. When combined
> with the fact that the streaming output terminals do not have controls,
> and therefore do not need to be addressable and lookup up by ID for
> anything else than matching with a streaming interface, this makes me
> think that ID collision between a streaming output terminal and another
> unit will likely be the most common case.
>
> > Tested with GRANDSTREAM GUV3100 in a 6.6 kernel.
> > ---
> > Changes in v2:
> > - Change Macro name
> > - Apply quirk only to TT_STEAMING
> > - Add missing suggested by
> > - uvc_stream_for_terminal
> > - Note, v2 has not been tested yet in real hardware, only v1.
> > - Link to v1: https://lore.kernel.org/r/20251022-uvc-grandstream-laurent-v1-1-0925738a3484@chromium.org
> > ---
> >  drivers/media/usb/uvc/uvc_driver.c | 31 ++++++++++++++++++++++++-------
> >  drivers/media/usb/uvc/uvcvideo.h   |  3 ++-
> >  2 files changed, 26 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
> > index fb6afb8e84f00961f86fd8f840fba48d706d7a9a..c0a2c05b0f13a8c3b14018c47dfb0be2614340ce 100644
> > --- a/drivers/media/usb/uvc/uvc_driver.c
> > +++ b/drivers/media/usb/uvc/uvc_driver.c
> > @@ -165,8 +165,10 @@ static struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev,
> >       return NULL;
> >  }
> >
> > -static struct uvc_streaming *uvc_stream_by_id(struct uvc_device *dev, int id)
> > +static struct uvc_streaming *uvc_stream_for_terminal(struct uvc_device *dev,
> > +                                                  struct uvc_entity *term)
> >  {
> > +     u16 id = UVC_HARDWARE_ENTITY_ID(term->id);
> >       struct uvc_streaming *stream;
> >
> >       list_for_each_entry(stream, &dev->streams, list) {
> > @@ -810,10 +812,12 @@ static struct uvc_entity *uvc_alloc_new_entity(struct uvc_device *dev, u16 type,
> >       }
> >
> >       /* Per UVC 1.1+ spec 3.7.2, the ID is unique. */
> > -     if (uvc_entity_by_id(dev, id)) {
> > -             dev_err(&dev->intf->dev, "Found multiple Units with ID %u\n", id);
> > +     if (uvc_entity_by_id(dev, UVC_HARDWARE_ENTITY_ID(id)))
> > +             dev_err(&dev->intf->dev, "Found multiple Units with ID %u\n",
> > +                     UVC_HARDWARE_ENTITY_ID(id));
> > +
> > +     if (uvc_entity_by_id(dev, id))
> >               id = UVC_INVALID_ENTITY_ID;
> > -     }
> >
> >       extra_size = roundup(extra_size, sizeof(*entity->pads));
> >       if (num_pads)
> > @@ -969,6 +973,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
> >       struct usb_host_interface *alts = dev->intf->cur_altsetting;
> >       unsigned int i, n, p, len;
> >       const char *type_name;
> > +     unsigned int id;
> >       u16 type;
> >
> >       switch (buffer[2]) {
> > @@ -1107,8 +1112,20 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
> >                       return 0;
> >               }
> >
> > +             id = buffer[3];
> > +
> > +             /*
> > +              * Nothing can be connected to an output terminal. To avoid
> > +              * entity-id's collisions in devices with invalid USB
> > +              * descriptors, move the output terminal id to its own
> > +              * namespace. Do this only for UVC_TT_STREAMING entities, to
> > +              * avoid changing the id of terminals with controls.
> > +              */
>
> How about expanding this too, similarly to the commit message to avoid
> digging all the information from the git history ? I've found that
> explaining hacks in more details helped me before when I had to rework
> the code years later.

I always like your comments :)

>
>                 /*
>                  * Some devices, such as the Grandstream GUV3100 and the LSK
>                  * Meeting Eye for Business & Home, exhibit entity ID collisions
I would not even Mention the LSK, they are abusing a vid:pid,.... up to you.
>                  * between units and streaming output terminals. Move streaming
>                  * output terminals to their own ID namespace by setting bit
>                  * UVC_TT_STREAMING (15), above the ID's 8-bit value. The bit is
UVC_TERM_OUTPUT
>                  * ignored in uvc_stream_for_terminal() when looking up the
>                  * streaming interface for the terminal.
>                  *
>                  * This hack is safe to enable unconditionally, asthe ID is not
as the
>                  * used for any other purpose (streaming output terminals have
>                  * no controls and are never referenced as sources in UVC
>                  * descriptors). Other types output terminals can have controls,
>                  * so limit usage of this separate namespace to streaming output
>                  * terminals.
>                  */
>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@...asonboard.com>
>
> > +             if (type & UVC_TT_STREAMING)
> > +                     id |= UVC_TERM_OUTPUT;
> > +
> >               term = uvc_alloc_new_entity(dev, type | UVC_TERM_OUTPUT,
> > -                                         buffer[3], 1, 0);
> > +                                         id, 1, 0);
> >               if (IS_ERR(term))
> >                       return PTR_ERR(term);
> >
> > @@ -2105,8 +2122,8 @@ static int uvc_register_terms(struct uvc_device *dev,
> >               if (UVC_ENTITY_TYPE(term) != UVC_TT_STREAMING)
> >                       continue;
> >
> > -             stream = uvc_stream_by_id(dev, term->id);
> > -             if (stream == NULL) {
> > +             stream = uvc_stream_for_terminal(dev, term);
> > +             if (!stream) {
> >                       dev_info(&dev->intf->dev,
> >                                "No streaming interface found for terminal %u.",
> >                                term->id);
> > diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
> > index ed7bad31f75ca474c1037d666d5310c78dd764df..3f2e832025e712585edc324afa6cad760d4edafc 100644
> > --- a/drivers/media/usb/uvc/uvcvideo.h
> > +++ b/drivers/media/usb/uvc/uvcvideo.h
> > @@ -41,7 +41,8 @@
> >  #define UVC_EXT_GPIO_UNIT            0x7ffe
> >  #define UVC_EXT_GPIO_UNIT_ID         0x100
> >
> > -#define UVC_INVALID_ENTITY_ID          0xffff
> > +#define UVC_HARDWARE_ENTITY_ID(id)   ((id) & 0xff)
> > +#define UVC_INVALID_ENTITY_ID                0xffff
> >
> >  /* ------------------------------------------------------------------------
> >   * Driver specific constants.
> >
> > ---
> > base-commit: ea299a2164262ff787c9d33f46049acccd120672
> > change-id: 20251022-uvc-grandstream-laurent-3f9abb8a0d5b
>
> --
> Regards,
>
> Laurent Pinchart



-- 
Ricardo Ribalda

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ