The branch main has been updated by bapt:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=4b9d794b6aa86a2b205e480928552d3f606d9bcc

commit 4b9d794b6aa86a2b205e480928552d3f606d9bcc
Author:     Baptiste Daroussin <[email protected]>
AuthorDate: 2026-07-22 07:25:52 +0000
Commit:     Baptiste Daroussin <[email protected]>
CommitDate: 2026-07-22 15:10:57 +0000

    uvideo: validate frame size before mmap buffer allocation
    
    dwMaxVideoFrameSize comes from the USB probe/commit response and is not
    validated.  reqbufs() computed buf_size_total with signed int arithmetic
    and no bound, so a bogus value could wrap the product to a small size
    and yield a too-small buffer with a huge sc_mmap_buffer_size, causing
    out-of-bounds writes from the USB transfer callbacks.
    
    Bound the frame size against sc_max_fbuf_size and use overflow-checked
    size_t arithmetic for the total and per-buffer offsets.
    
    Reported by:    emaste
---
 sys/dev/usb/video/uvideo.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/sys/dev/usb/video/uvideo.c b/sys/dev/usb/video/uvideo.c
index bb4d42778998..9c6076bc76d0 100644
--- a/sys/dev/usb/video/uvideo.c
+++ b/sys/dev/usb/video/uvideo.c
@@ -3531,7 +3531,9 @@ uvideo_g_input(struct uvideo_softc *sc, int *input)
 static int
 uvideo_reqbufs(struct uvideo_softc *sc, struct v4l2_requestbuffers *rb)
 {
-       int i, buf_size, buf_size_total;
+       int i;
+       uint32_t buf_size;
+       size_t buf_size_total;
        vm_object_t obj;
        vm_offset_t kva;
        int error;
@@ -3552,7 +3554,12 @@ uvideo_reqbufs(struct uvideo_softc *sc, struct 
v4l2_requestbuffers *rb)
                sc->sc_mmap_count = rb->count;
 
        buf_size = UGETDW(sc->sc_desc_probe.dwMaxVideoFrameSize);
-       buf_size_total = sc->sc_mmap_count * buf_size;
+       if (buf_size == 0 || sc->sc_max_fbuf_size <= 0 ||
+           buf_size > (u_int)sc->sc_max_fbuf_size)
+               return (EINVAL);
+       if (SIZE_MAX / sc->sc_mmap_count < buf_size)
+               return (EINVAL);
+       buf_size_total = (size_t)sc->sc_mmap_count * buf_size;
        buf_size_total = round_page(buf_size_total);
 
        /*
@@ -3599,10 +3606,11 @@ uvideo_reqbufs(struct uvideo_softc *sc, struct 
v4l2_requestbuffers *rb)
            buf_size_total, (uintmax_t)kva);
 
        for (i = 0; i < sc->sc_mmap_count; i++) {
-               sc->sc_mmap[i].buf = sc->sc_mmap_buffer + (i * buf_size);
+               sc->sc_mmap[i].buf = sc->sc_mmap_buffer +
+                   ((size_t)i * buf_size);
 
                sc->sc_mmap[i].v4l2_buf.index = i;
-               sc->sc_mmap[i].v4l2_buf.m.offset = i * buf_size;
+               sc->sc_mmap[i].v4l2_buf.m.offset = (size_t)i * buf_size;
                sc->sc_mmap[i].v4l2_buf.length = buf_size;
                sc->sc_mmap[i].v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                sc->sc_mmap[i].v4l2_buf.sequence = 0;

Reply via email to