From nobody Mon Sep 28 15:34:41 2026 Received: from mail-106113.protonmail.ch (mail-106113.protonmail.ch [79.135.106.113]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B4B5D41D642 for ; Thu, 20 Aug 2026 11:16:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.135.106.113 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787224585; cv=none; b=IYXESgZ1gmbBOaD211RdHcSxx7y3F/Bli44T5fn+t99UkHcg22hqdwhNxL3AEF48+mTtrsL8JBzysgTl1GZKB3oVOMxnK4Mly+usis4w8xQ+rHfu9NzqY5sNiyRMEDwRiaSoEh9kfO6L8ewfnRioZQ2ipZHBcFS5eQVJbasXPSI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787224585; c=relaxed/simple; bh=i1YRnDEs7RKAczXpM4GNiorJvmoYtNBtPMjrYFo/qNs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=pLwBYDLrPfeSNsJUCyjMaboPrkwRqVtffw+E3UCD0+dakAdOFvdZegnWWk42D9lxoqOsP+Mc/zARAE3ePHImc7KM5CejfVxRCPpf2Z4pfU9r6izjc6mhDSQHh9O+DfWdY7vbfqSGX7TOX2yHYCQXERgbyXok8EijHVxwmJmwVHk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=runtimeverification.com; spf=pass smtp.mailfrom=runtimeverification.com; dkim=pass (2048-bit key) header.d=runtimeverification.com header.i=@runtimeverification.com header.b=JfRx1o8o; arc=none smtp.client-ip=79.135.106.113 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=runtimeverification.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=runtimeverification.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=runtimeverification.com header.i=@runtimeverification.com header.b="JfRx1o8o" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=runtimeverification.com; s=protonmail; t=1787224578; x=1787483778; bh=LR78WkMGrhZNAj6P4HYb1ppkVtN8Zbi+rJKZgCG+z3Y=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:From:To: Cc:Date:Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector; b=JfRx1o8oW1UYmiggTowPyX8z3RYJ3TccEejiWR3T0hilPdnf+NgOiJQC6hlhDbTP/ tdVuc48IvWFpH4WApRe2YqeIUZBrNN5k8qiercbyayl+FSePBkObWnu5D13XOJjJ9D fwrQhAJ1MMGC8SEq0RSVcT+fQ6CwrV9fYn3RkFs4ER9JGkw+gkKkGeYr9zJAEysi2C bKLpE7XuU43ghWevT98Z7H0SyMjbGifaA/z9v2mSVXuX+/WsxI7VAFKxKTh4mHRj7u oQfmcF+qfUP76GCffc4ndTJ5fvqrfXvblFCL4TFv6gnlaLYIjJGbCIXY0daIBqw2j9 ZCY0nvgxbY6Jw== X-Pm-Submission-Id: 4hQgqH5gPvz2SchM From: Natasha Klaus To: laurent.pinchart@ideasonboard.com, hansg@kernel.org, mchehab@kernel.org Cc: ribalda@chromium.org, noambs2999@gmail.com, david.laight.linux@gmail.com, linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, Natasha Klaus , stable@vger.kernel.org Subject: [PATCH v3 1/3] media: uvcvideo: Let uvc_parse_frame() report a skipped frame Date: Thu, 20 Aug 2026 14:15:54 +0300 Message-Id: <20260820111556.232652-2-natalie.klaus@runtimeverification.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260820111556.232652-1-natalie.klaus@runtimeverification.com> References: <20260820111556.232652-1-natalie.klaus@runtimeverification.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" uvc_parse_frame() returns the descriptor length on success and a negative error code on failure, and uvc_parse_format() treats every negative value as fatal for the whole streaming interface. There is no way for the parser to say "this frame descriptor is unusable, but the rest of the format is fine". Change the return convention so it can. Return 0 on success and let the caller advance by buffer[0], which is the value the function returned anyway. Report a truncated descriptor with -ENODATA, which stays fatal, and leave every other negative value to mean "skip this frame descriptor and carry on with the next one". -ENODATA is currently the only error the function can return, so the skip path is unreachable until later patches add checks that use it. The one behavioural change is the truncated-descriptor diagnostic, which moves from uvc_dbg() to dev_warn() so a malformed descriptor is reported without the DESCR debug flag. That leaves the local alts variable unused, and the kernel builds -Wunused-variable as an error, so it goes too. Suggested-by: Ricardo Ribalda Link: https://lore.kernel.org/linux-media/CANiDSCue8yyiGubzbAybRqSUTTFuB=3D= -Y2TZy6yvOx32SpAASWg@mail.gmail.com/ Cc: stable@vger.kernel.org Reviewed-by: Ricardo Ribalda Tested-by: Noam Ben Shimon Signed-off-by: Natasha Klaus --- The Cc: stable line is present without a Fixes: tag because this patch is a prerequisite for 2/3 rather than a fix in its own right. Stable needs both or neither: backported alone, 2/3's -EINVAL would revert to meaning "discard the whole streaming interface". The caller checks -ENODATA before counting the frame, per Ricardo's review. Behaviour is unchanged either way, since -ENODATA is non-zero, but the fatal case reads better first. drivers/media/usb/uvc/uvc_driver.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc= _driver.c index e289cc71ba98..b94fe5366e55 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -230,7 +230,6 @@ static int uvc_parse_frame(struct uvc_device *dev, u32 **intervals, u8 ftype, int width_multiplier, const unsigned char *buffer, int buflen) { - struct usb_host_interface *alts =3D streaming->intf->cur_altsetting; unsigned int maxIntervalIndex; unsigned int interval; unsigned int i, n; @@ -243,10 +242,10 @@ static int uvc_parse_frame(struct uvc_device *dev, n =3D n ? n : 3; =20 if (buflen < 26 + 4 * n) { - uvc_dbg(dev, DESCR, - "device %d videostreaming interface %d FRAME error\n", - dev->udev->devnum, alts->desc.bInterfaceNumber); - return -EINVAL; + dev_warn(&streaming->intf->dev, + "UVC non compliance: FRAME descriptor is %d bytes, expected at least %= u.\n", + buflen, 26 + 4 * n); + return -ENODATA; } =20 frame->bFrameIndex =3D buffer[3]; @@ -329,7 +328,7 @@ static int uvc_parse_frame(struct uvc_device *dev, =20 *intervals +=3D n; =20 - return buffer[0]; + return 0; } =20 static int uvc_parse_format(struct uvc_device *dev, @@ -492,11 +491,12 @@ static int uvc_parse_format(struct uvc_device *dev, ret =3D uvc_parse_frame(dev, streaming, format, frame, intervals, ftype, width_multiplier, buffer, buflen); - if (ret < 0) + if (ret =3D=3D -ENODATA) return ret; - format->nframes++; - buflen -=3D ret; - buffer +=3D ret; + if (!ret) + format->nframes++; + buflen -=3D buffer[0]; + buffer +=3D buffer[0]; } } =20 --=20 2.34.1 From nobody Mon Sep 28 15:34:41 2026 Received: from mail-106113.protonmail.ch (mail-106113.protonmail.ch [79.135.106.113]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5B4714248C8; Thu, 20 Aug 2026 11:16:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.135.106.113 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787224589; cv=none; b=EFF3sSkxB6ur5ZNYVp/L3ppp4uVZZabkh0+Tx0amPNvnpMwNANRSoOiHaHbb21DkHTTky3lgzlsXh15heoNgC377lleJdL1iuA1cLgI+EnrtUSMvFWokKYgwSONIkFvYGpQrRDpenTjN4bxxiaHBfV3bFXrb5POVp4duGitYYHQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787224589; c=relaxed/simple; bh=DNfK/5YTWMuhE6vG0H6dQxOVy/hb2P4VlH+EzBuF/Ng=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=QVY7++ONzcLfyUJpTCd8Vcasxan74cQH772UZK2n90p9Jw1QsstSSVyisNvAq9Zp27xxg3JxOolHTgDMLtBy5KqGP9LfGqYefAiwq3t5AgC+1xi0HXt1msgcJIM6ssjoniE2Yb4yRRyIWhGZmtDDTWPTIJjCAO+zgyasOr8dRFw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=runtimeverification.com; spf=pass smtp.mailfrom=runtimeverification.com; dkim=pass (2048-bit key) header.d=runtimeverification.com header.i=@runtimeverification.com header.b=MMWIknHB; arc=none smtp.client-ip=79.135.106.113 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=runtimeverification.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=runtimeverification.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=runtimeverification.com header.i=@runtimeverification.com header.b="MMWIknHB" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=runtimeverification.com; s=protonmail; t=1787224584; x=1787483784; bh=jgdK7kRhSX2y/N1DUJ1hdSSiBvEekYXI93e3DnBsE1g=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:From:To: Cc:Date:Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector; b=MMWIknHBW0hRBZuXTD/OKWHfDkJM4XMRdmsSk+vZAHEvv+aMVbXSbwHGZ/rgOYBPo DAsHZlRueYkcfqgn+3OolKlfa+Di7hZsiCJvnEXx0p/nuSJoZ2P+TuZ0gTWPQKWuei dylaqvrXe5z0mxVGubjkSBa3DQzGZNpWecbVyi78BvMN4IpJ2Iihd8Fsqn0tD0OasT fDwzwfXgPW8mN8cIyl7WgxOnZ5gC9b9PfXKq+uOBYps3TIp0grzE+yEAknk/G1Z4Mu 6ZwsmVDcK3j4k0MZm2plEuXKq94HUmC7lN668xlCGZNXxNs8c61YfSa8JxmynvoRVp 0/+adkgtAa77g== X-Pm-Submission-Id: 4hQgqS4Pqwz2SchM From: Natasha Klaus To: laurent.pinchart@ideasonboard.com, hansg@kernel.org, mchehab@kernel.org Cc: ribalda@chromium.org, noambs2999@gmail.com, david.laight.linux@gmail.com, linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org, Natasha Klaus Subject: [PATCH v3 2/3] media: uvcvideo: Fix integer overflow in frame buffer size calculation Date: Thu, 20 Aug 2026 14:15:55 +0300 Message-Id: <20260820111556.232652-3-natalie.klaus@runtimeverification.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260820111556.232652-1-natalie.klaus@runtimeverification.com> References: <20260820111556.232652-1-natalie.klaus@runtimeverification.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Noam Ben Shimon In the function uvc_parse_frame(), it recomputes dwMaxVideoFrameBufferSize for uncompressed formats. This helps working around devices that report it wrong: frame->dwMaxVideoFrameBufferSize =3D format->bpp * frame->wWidth * frame->wHeight / 8; These three arguments originate from the device's own descriptors, and therefore can be decided by it. bpp is a u8 and wWidth and wHeight are u16. The expression is evaluated in int, and the maximum value is 255 * 65535 * 65535 (which is roughly 510 times INT_MAX). A device that declares large dimensions therefore overflows a signed int here. The kernel is built using -fno-strict-overflow, so this wraps rather than being miscompiled, but the wrapped value (which is often negative) is then divided by 8 and stored in a u32 used as a size. Two examples for this (using legal field values): - 32 bpp, 16384x4096: the product is exactly 2^31 and wraps to INT_MIN. After division and conversion to u32 the field has the value 4026531840 rather than 268435456. - 16 bpp, 16384x16384: the product is exactly 2^32 and wraps to 0. The field holds 0, rather than the correct 536870912. I don't think memory corruption is a consequence of this. The value reaches uvc_queue_setup() as the vb2 buffer size, and every copy on the decode path is bounded by buf->length, which uvc_buffer_prepare() gets from vb2_plane_size() rather than this field. What a wrapped value does instead is make the driver describe the stream inconsistently. For an uncompressed format uvc_fixup_video_ctrl() copies it into ctrl->dwMaxVideoFrameSize unconditionally, and that becomes the sizeimage reported by VIDIOC_G_FMT. This is while width, height and bytesperline continue to describe the full frame. This also makes uvc_video_validate_buffer() mark error on all frames, because it is comparing bytesused against the same number. Compute the size in 64-bit, and if the result does not fit in the u32 field then skip the frame descriptor. An uncompressed frame this large is probably not a real device, and skipping it leaves the rest of the format and the streaming interface usable. The rounding also changes from truncation to round-up. Truncation is pre-existing rather than introduced here: the original expression used integer division, so it has rounded a partial trailing byte away since the driver was merged. Rounding up is the right direction for a buffer size, and DIV_ROUND_UP() against BITS_PER_BYTE is what the rest of the media tree uses for this computation, including uvc_parse_format() itself for the FORCE_BPP quirk. Fixes: c0efd232929c ("V4L/DVB (8145a): USB Video Class driver") Cc: stable@vger.kernel.org Signed-off-by: Noam Ben Shimon Reviewed-by: Ricardo Ribalda Tested-by: Noam Ben Shimon Signed-off-by: Natasha Klaus --- Changes from Noam's v2: - Rebased onto patch 1/3; this patch no longer applies standalone. - Diagnostic changed from uvc_dbg(dev, DESCR, ...) to dev_warn() on &streaming->intf->dev, reworded to begin "UVC non compliance: " and to say the frame is skipped. The explicit device and interface numbers are dropped from the message text because dev_warn() already identifies the interface. (The original could not be kept as-is in any case: patch 1/3 removes the local alts variable it referenced.) - bpp, wWidth and wHeight added to the message text (David Laight), matching the wording of the diagnostic in 3/3. - The >> 3 replaced with DIV_ROUND_UP() against BITS_PER_BYTE (David Laight= ), so a partial trailing byte is no longer dropped. The overflow check is applied to the rounded-up value. - The return value is still -EINVAL; what changed is its meaning, which patch 1/3 redefines as "skip this frame descriptor" rather than "fail the whole streaming interface". - Last paragraph of the commit message reworded from "reject the frame descriptor ... rejection is consistent with the other checks over malformed-descriptors in this function" to describe skipping instead, and a paragraph added on the rounding change. - Ricardo Ribalda's Reviewed-by dropped, as it was given on the unmodified v2. - Submitter's Signed-off-by added. - Fixes: and Cc: stable lines unchanged. - DIV_ROUND_UP changed to DIV_ROUND_UP_ULL per Ricardo's review. Rounding up also moves the U32_MAX boundary: two inputs within the field limits (bpp=3D79 at 10077x43161 and bpp=3D237 at 3359x43161) landed exactly= on U32_MAX with the old truncation and are now rejected, since the rounded-up size is not representable. Build tested on x86_64; see the cover letter for Noam's gadget testing. drivers/media/usb/uvc/uvc_driver.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc= _driver.c index b94fe5366e55..d7d71418f875 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -295,9 +295,21 @@ static int uvc_parse_frame(struct uvc_device *dev, * information. For uncompressed formats this can be fixed by computing * the value from the frame size. */ - if (!(format->flags & UVC_FMT_FLAG_COMPRESSED)) - frame->dwMaxVideoFrameBufferSize =3D format->bpp * frame->wWidth - * frame->wHeight / 8; + if (!(format->flags & UVC_FMT_FLAG_COMPRESSED)) { + u64 bufsize; + + bufsize =3D DIV_ROUND_UP_ULL((u64)format->bpp * frame->wWidth * + frame->wHeight, BITS_PER_BYTE); + if (bufsize > U32_MAX) { + dev_warn(&streaming->intf->dev, + "UVC non compliance: FRAME %u computed buffer size overflows (%ux%u, = %u bpp), skipping it.\n", + frame->bFrameIndex, frame->wWidth, + frame->wHeight, format->bpp); + return -EINVAL; + } + + frame->dwMaxVideoFrameBufferSize =3D bufsize; + } =20 /* * Clamp the default frame interval to the boundaries. A zero --=20 2.34.1 From nobody Mon Sep 28 15:34:41 2026 Received: from mail-43170.protonmail.ch (mail-43170.protonmail.ch [185.70.43.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2FAE841F7D8 for ; Thu, 20 Aug 2026 11:16:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.70.43.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787224599; cv=none; b=d4jOZUp4WRtN5TiJa6sW33ikX/CCctl1d+66nav3Dc7tTv5sKGPuleCOu4ZyH9hSP/nAyB4f9ouUknhcB9+611uSqiLf6OVzapJGSIiRjh3wyd1peUCuHD6JJR4vR4BSYt/bL38mru1Rk7Q9n53s+Bykcm4Cr99PaWSQbO9G41I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787224599; c=relaxed/simple; bh=C8wGWkUosH7Ke7vUDqhzuP+EqzM3vrSbJtc83k/sSRs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=XpDqQZeqghMbXAJYMxxPCtRNEswQ11PZ6Yh/WzY79D8Q8kBSFYqWG+XgOOY8EPeTOacBHXvvyR4rgCrAK8E+m4ZFeKviUcyGD+brjJ1YeFK7M+ofBw1QoWri1Lq2d7A152P717XOgIcqxVrV8cUwpXlDU7F4voyGyG2SJY8eHT4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=runtimeverification.com; spf=pass smtp.mailfrom=runtimeverification.com; dkim=pass (2048-bit key) header.d=runtimeverification.com header.i=@runtimeverification.com header.b=tlSjSkWb; arc=none smtp.client-ip=185.70.43.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=runtimeverification.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=runtimeverification.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=runtimeverification.com header.i=@runtimeverification.com header.b="tlSjSkWb" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=runtimeverification.com; s=protonmail; t=1787224592; x=1787483792; bh=/7PgSPWO26oHfxumucIrOt3i9/Rs420zWU6/UZ9efVg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:From:To: Cc:Date:Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector; b=tlSjSkWbRDEpn8JFRsfl//W43wvrmYHWFOHlO0nO8QURLtOzDtJvGQn9YE5gCbV2W 80Lj3WD5F4yAQc6BBstvqE2qnQRvy14JQhHTVuIZiRS1ZM+aFP9RSc+HPMF0H7VhP4 zEvG4wPICqkey39LElXn2I9MreztVKotc9s33i6qzmwPGtx7gLbsXLIq/TUIuYQ9Fe 0EHgKFKqm7qLyiR+wlYUNmQrXFLb/f6Wt7gM2qvlT4/UpYUQMYYRTkiDlJv2K77yjM SseVmQcW1VTCvtsTQigaB1ObtTVGp93eKBh2kZLoVOcNURzujE+dvggxW4tYFkEjSq 4xz8DofFB+kVg== X-Pm-Submission-Id: 4hQgqb429Wz2SchM From: Natasha Klaus To: laurent.pinchart@ideasonboard.com, hansg@kernel.org, mchehab@kernel.org Cc: ribalda@chromium.org, noambs2999@gmail.com, david.laight.linux@gmail.com, linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, Natasha Klaus Subject: [PATCH v3 3/3] media: uvcvideo: Skip frame descriptors with a zero computed size Date: Thu, 20 Aug 2026 14:15:56 +0300 Message-Id: <20260820111556.232652-4-natalie.klaus@runtimeverification.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260820111556.232652-1-natalie.klaus@runtimeverification.com> References: <20260820111556.232652-1-natalie.klaus@runtimeverification.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" For uncompressed formats uvc_parse_frame() recomputes dwMaxVideoFrameBufferSize from the frame dimensions and the bits per pixel. All three operands are read straight from the descriptor bytes with no range check, so the computed size is zero whenever any of them is zero. A zero size is not harmless. It is copied into ctrl->dwMaxVideoFrameSize by uvc_fixup_video_ctrl() and reaches uvc_queue_setup() as the vb2 plane size, where it trips WARN_ON(!plane_sizes[i]) in vb2_core_reqbufs() at drivers/media/common/videobuf2/videobuf2-core.c:951 and fails VIDIOC_REQBUFS with -EINVAL. On a kernel built with panic_on_warn that WARN is fatal. Such a frame can also become the active one without any application asking for it: when no frame matches the device's default bFrameIndex, uvc_video_init() falls back to frames[0], so a device that also has usable frames can come up unusable. Skip the frame rather than rejecting the descriptor, which would discard the whole streaming interface and every valid format on it. This follows commit 81f3affa19d6 ("media: uvcvideo: Don't expose unsupported formats to userspace"), which drops a format descriptor the driver cannot use for the same reason: to keep it from reaching userspace and triggering a WARN_ON. Reviewed-by: Ricardo Ribalda Tested-by: Noam Ben Shimon Signed-off-by: Natasha Klaus --- Depends on 1/3 for -EINVAL to mean "skip this frame", and on 2/3 for the bufsize local. After 2/3 rounds up instead of truncating, the computed size is zero only when one of bpp, wWidth or wHeight is zero; the "product below 8 truncates to zero" case no longer exists. drivers/media/usb/uvc/uvc_driver.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc= _driver.c index d7d71418f875..0bb4e17711cf 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -308,6 +308,20 @@ static int uvc_parse_frame(struct uvc_device *dev, return -EINVAL; } =20 + /* + * A zero-sized frame is unusable: it reaches vb2 as a zero + * plane size, and it is reported to userspace as a 0x0 frame + * with a zero sizeimage. Skip the frame descriptor, the + * caller moves on to the next one. + */ + if (!bufsize) { + dev_warn(&streaming->intf->dev, + "UVC non compliance: FRAME %u has zero size (%ux%u, %u bpp), skipping= it.\n", + frame->bFrameIndex, frame->wWidth, + frame->wHeight, format->bpp); + return -EINVAL; + } + frame->dwMaxVideoFrameBufferSize =3D bufsize; } =20 --=20 2.34.1