DF-1011 / fix.diff
diff --git a/sys/bus/u4b/uvc/uvc_drv.c b/sys/bus/u4b/uvc/uvc_drv.c --- a/sys/bus/u4b/uvc/uvc_drv.c +++ b/sys/bus/u4b/uvc/uvc_drv.c @@ -1671,7 +1671,7 @@ struct uvc_vs_frame_desc *fdesc; struct uvc_vs_frame_based_desc *fbdesc; uint32_t size; - uint16_t nfmt, nfrm, nitv; + uint32_t nfmt, nfrm, nitv; /* DF-1011: was uint16_t -> nitv wraps */ nfmt = nfrm = nitv = 0; desc = NULL; @@ -1701,12 +1701,24 @@ break; case UDESCSUB_VS_FRAME_MJPEG: fdesc = (struct uvc_vs_frame_desc *)desc; + /* DF-1011: bFrameIntervalType is a device-controlled uByte that + * claims how many dFrameInterval[] entries follow the 26-byte + * frame header. Validate it against bLength so the parse loop + * does not read past this descriptor (and so the summed nitv + * cannot be inflated to wrap the allocator). */ + if (fdesc->bLength < 26 || + fdesc->bFrameIntervalType > (fdesc->bLength - 26) / 4) + return EINVAL; nfrm++; nitv += (fdesc->bFrameIntervalType > 0) ? fdesc->bFrameIntervalType : 3; break; case UDESCSUB_VS_FRAME_FRAME_BASED: fbdesc = (struct uvc_vs_frame_based_desc *)desc; + /* DF-1011: frame-based header is 30 bytes before dFrameInterval[]. */ + if (fbdesc->bLength < 30 || + fbdesc->bFrameIntervalType > (fbdesc->bLength - 30) / 4) + return EINVAL; nfrm++; nitv += (fbdesc->bFrameIntervalType > 0) ? fbdesc->bFrameIntervalType : 3; diff --git a/sys/bus/u4b/uvc/uvc_drv.h b/sys/bus/u4b/uvc/uvc_drv.h --- a/sys/bus/u4b/uvc/uvc_drv.h +++ b/sys/bus/u4b/uvc/uvc_drv.h @@ -659,9 +659,9 @@ struct usb_xfer *xfer[UVC_N_BULKTRANSFER]; /* data format */ - uint8_t nfmt; - uint8_t nfrm; - uint8_t nitv; + uint32_t nfmt; /* DF-1011: was uint8_t, truncated on store */ + uint32_t nfrm; /* DF-1011: was uint8_t, truncated on store */ + uint32_t nitv; /* DF-1011: was uint8_t, truncated on store */ uint8_t unuse[3]; struct uvc_data_format *fmt; }; |