DF-2348 / fix.diff
diff --git a/sys/bus/u4b/uvc/uvc_buf.c b/sys/bus/u4b/uvc/uvc_buf.c --- a/sys/bus/u4b/uvc/uvc_buf.c +++ b/sys/bus/u4b/uvc/uvc_buf.c @@ -104,16 +104,21 @@ static __inline int uvc_buf_queue_mmap_locked(struct uvc_buf_queue *bq, vm_paddr_t *paddr, vm_offset_t offset) { - uint64_t max_offset = (uint64_t)(bq->buf_size * bq->buf_count) - PAGE_SIZE; + uint64_t total, max_offset; if (bq->mem == NULL) return EINVAL; - if (offset < 0) + /* Guard against overflow/underflow: a malicious webcam can report + dwMaxVideoSize=0 (kmalloc(0)=ZERO_LENGTH_PTR, buf_size=0) which made + the old 'max_offset < 0' check a dead unsigned comparison. */ + if (bq->buf_count != 0 && + bq->buf_size > (uint64_t)-1 / bq->buf_count) return EINVAL; - - if (max_offset < 0) + total = (uint64_t)bq->buf_size * bq->buf_count; + if (total < PAGE_SIZE) return EINVAL; + max_offset = total - PAGE_SIZE; if (offset > max_offset) { kprintf("WARNING: %s offset out of bound: %ld\n; max: %ld", |