Re: [PATCH v2] media: uvcvideo: Fix integer overflow in frame buffer size calculation

Ricardo Ribalda <[email protected]>
Newsgroups org.kernel.vger.linux-media,org.kernel.vger.linux-kernel
Message-ID <CANiDSCuMJ6A+0aC32Fz18P4x=of6Ww0FgudVXHKOtXFx09fjDA@mail.gmail.com>
Hi Natasha

Thanks for the thorough review


On Tue, 18 Aug 2026 at 08:45, Natasha Klaus
<[email protected]> wrote:
>
> On Wed, Aug 12, 2026 at 01:32:51PM +0300, Noam Ben Shimon wrote:
> > +     if (!(format->flags & UVC_FMT_FLAG_COMPRESSED)) {
> > +             u64 bufsize;
> > +
> > +             bufsize = ((u64)format->bpp * frame->wWidth * frame->wHeight) >> 3;
> > +             if (bufsize > U32_MAX) {
> > +                     uvc_dbg(dev, DESCR,
> > +                             "device %d videostreaming interface %d FRAME %u: computed buffer size overflows\n",
> > +                             dev->udev->devnum,
> > +                             alts->desc.bInterfaceNumber,
> > +                             frame->bFrameIndex);
> > +                     return -EINVAL;
> > +             }
> > +
> > +             frame->dwMaxVideoFrameBufferSize = bufsize;
> > +     }
>
> Ricardo asked me to look at this. I had been looking at the same expression
> independently, so I checked your numbers and the surrounding behaviour
> rather than only the diff.
>
> Both examples in the commit message reproduce exactly. 32 bpp at
> 16384x4096 gives 4026531840 against a true 268435456, and 16 bpp at
> 16384x16384 gives 0 against 536870912.
>
> One case I would add to the commit message, because it is the strongest
> argument for rejecting rather than only widening. bpp=32 at 32768x32768
> is exactly 2^35, so the 64-bit quotient is exactly 2^32. A bare (u64)
> cast without your check would store 0 there, which is the same failure
> the patch removes. Your check catches it.
>
> I also checked when the check can fire at all. For bpp <= 8 the threshold
> is unreachable given the u16 field limits, and it does not need to be
> reachable: the largest possible result at bpp=8 is 4294836225, which
> still fits in u32. So the check fires exactly where it is needed and
> nowhere else. That seemed worth confirming rather than assuming.
>
> My one question is about the error path rather than the arithmetic.
>
> uvc_parse_frame() has a single caller, and -EINVAL propagates further
> than I first expected:
>
>   uvc_driver.c:495   return ret, so the whole format is abandoned
>   uvc_driver.c:745   goto error, so remaining formats are never parsed
>   uvc_driver.c:788   usb_driver_release_interface() and uvc_stream_delete(),
>                      so the streaming interface never reaches dev->streams
>   uvc_driver.c:1004  the uvc_parse_streaming() return value is discarded,
>                      so probe continues and succeeds
>   uvc_driver.c:2135  "No streaming interface found for terminal %u"
>
> So one malformed frame descriptor costs the entire streaming interface,
> not just that frame, and probe still succeeds. On a single-interface
> webcam that means the device binds with no /dev/videoN, and the only
> explanation is the uvc_dbg line above, which sits behind a debug bit
> that is off by default.
>
> I do not think this is a practical regression risk, since no plausible
> device reaches 2^35, and the surrounding function is otherwise built
> around repairing bad descriptors rather than rejecting them. What
> bothers me is the silence: a user who does trip it sees a device that
> binds and produces nothing, with no logged reason. Two ways to address
> that:
>
>   - dev_warn() instead of uvc_dbg(), so the reason is visible without a
>     debug build
>   - skip only that frame descriptor and continue, rather than failing
>     the format

Good point. if you send a v3. please use:
 dev_warn_once(&dev->intf->dev, "UVC non compliance: blah blah foo bar"...)

We are trying to standarize the "UVC non compliance" string



>
> Either would satisfy me. If you and the maintainers would rather keep
> -EINVAL with uvc_dbg as it stands, I have no objection to that either,
> and you are welcome to add
>
> Reviewed-by: Natasha Klaus <[email protected]>
>
> to v2 as it is.
>
> Separately, and explicitly not an objection to this patch: a zero
> dwMaxVideoFrameBufferSize stays reachable from the other end. Any zero
> operand, or any product below 8, gives 0 after the shift, and bpp=0 does
> reach the computation on uncompressed formats. Nothing between the
> descriptor bytes at uvc_driver.c:254, :255 and :382 and this line
> validates any of the three. A zero then goes through uvc_video.c:214
> into stream->ctrl, sizes vb2 at uvc_queue.c:90, and trips
> WARN_ON(!plane_sizes[i]) in vb2_core_reqbufs() at
> videobuf2-core.c:951. That is pre-existing and unchanged by your patch,
> so it is not yours to fix here. I am happy to send a follow-up if the
> maintainers want it as a separate change.

Happy to review it if you send it :)

>
> One caveat on my side: all of the above comes from reading the tree at
> v7.2, not from running it. I did not test on hardware or a UVC gadget,
> and I did not build your patch.
>
> Natasha



-- 
Ricardo Ribalda
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.