Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/usb Better descriptor parsing.
details: https://anonhg.NetBSD.org/src/rev/26f0957ad6f5
branches: trunk
changeset: 374201:26f0957ad6f5
user: mlelstv <mlelstv%NetBSD.org@localhost>
date: Mon Apr 10 15:26:56 2023 +0000
description:
Better descriptor parsing.
Add sanity check if no default format is found.
diffstat:
sys/dev/usb/uvideo.c | 50 ++++++++++++++++++++++++++++++++++++------------
sys/dev/usb/uvideoreg.h | 11 ++++++---
2 files changed, 44 insertions(+), 17 deletions(-)
diffs (163 lines):
diff -r 04cb149a09ee -r 26f0957ad6f5 sys/dev/usb/uvideo.c
--- a/sys/dev/usb/uvideo.c Mon Apr 10 15:14:50 2023 +0000
+++ b/sys/dev/usb/uvideo.c Mon Apr 10 15:26:56 2023 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: uvideo.c,v 1.83 2022/07/01 01:06:51 riastradh Exp $ */
+/* $NetBSD: uvideo.c,v 1.84 2023/04/10 15:26:56 mlelstv Exp $ */
/*
* Copyright (c) 2008 Patrick Mahoney
@@ -42,7 +42,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvideo.c,v 1.83 2022/07/01 01:06:51 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvideo.c,v 1.84 2023/04/10 15:26:56 mlelstv Exp $");
#ifdef _KERNEL_OPT
#include "opt_usb.h"
@@ -442,12 +442,8 @@ static void print_vs_format_dv_descripto
const uvideo_vs_format_dv_descriptor_t *);
#endif /* !UVIDEO_DEBUG */
-#define GET(type, descp, field) \
- (KASSERT((descp)->bLength >= sizeof(type)), \
- ((const type *)(descp))->field)
-#define GETP(type, descp, field) \
- (KASSERT((descp)->bLength >= sizeof(type)), \
- &(((const type *)(descp))->field))
+#define GET(type, descp, field) (((const type *)(descp))->field)
+#define GETP(type, descp, field) (&(((const type *)(descp))->field))
/*
* Given a format descriptor and frame descriptor, copy values common
@@ -1312,6 +1308,13 @@ uvideo_stream_free(struct uvideo_stream
kmem_free(vs, sizeof(*vs));
}
+#define framedesc_size(T, d) ( \
+ offsetof(T, uFrameInterval) + \
+ ((T *)(d))->bFrameIntervalType \
+ ? ((T *)(d))->bFrameIntervalType \
+ * sizeof(((T *)(d))->uFrameInterval.discrete) \
+ : sizeof(((T *)(d))->uFrameInterval.continuous) \
+)
static usbd_status
uvideo_stream_init_frame_based_format(struct uvideo_stream *vs,
@@ -1342,7 +1345,6 @@ uvideo_stream_init_frame_based_format(st
return USBD_INVAL;
}
subtype = UDESC_VS_FRAME_UNCOMPRESSED;
- subtypelen = sizeof(uvideo_vs_frame_uncompressed_descriptor_t);
default_index = GET(uvideo_vs_format_uncompressed_descriptor_t,
format_desc,
bDefaultFrameIndex);
@@ -1372,7 +1374,6 @@ uvideo_stream_init_frame_based_format(st
return USBD_INVAL;
}
subtype = UDESC_VS_FRAME_FRAME_BASED;
- subtypelen = sizeof(uvideo_frame_frame_based_descriptor_t);
default_index = GET(uvideo_format_frame_based_descriptor_t,
format_desc,
bDefaultFrameIndex);
@@ -1386,7 +1387,6 @@ uvideo_stream_init_frame_based_format(st
return USBD_INVAL;
}
subtype = UDESC_VS_FRAME_MJPEG;
- subtypelen = sizeof(uvideo_vs_frame_mjpeg_descriptor_t);
default_index = GET(uvideo_vs_format_mjpeg_descriptor_t,
format_desc,
bDefaultFrameIndex);
@@ -1398,8 +1398,6 @@ uvideo_stream_init_frame_based_format(st
return USBD_INVAL;
}
- KASSERT(subtypelen >= sizeof(*uvdesc));
-
pformat = NULL;
SIMPLEQ_FOREACH(pfiter, &vs->vs_pixel_formats, entries) {
if (pfiter->pixel_format == pixel_format) {
@@ -1432,6 +1430,29 @@ uvideo_stream_init_frame_based_format(st
uvdesc = (const uvideo_descriptor_t *)desc;
if (uvdesc->bDescriptorSubtype != subtype)
break;
+
+ switch (format_desc->bDescriptorSubtype) {
+ case UDESC_VS_FORMAT_UNCOMPRESSED:
+ subtypelen = framedesc_size(
+ const uvideo_vs_frame_uncompressed_descriptor_t,
+ uvdesc);
+ break;
+ case UDESC_VS_FORMAT_MJPEG:
+ subtypelen = framedesc_size(
+ const uvideo_vs_frame_mjpeg_descriptor_t,
+ uvdesc);
+ break;
+ case UDESC_VS_FORMAT_FRAME_BASED:
+ subtypelen = framedesc_size(
+ const uvideo_frame_frame_based_descriptor_t,
+ uvdesc);
+ break;
+ default:
+ /* will bail out below */
+ subtypelen = uvdesc->bLength;
+ break;
+ }
+
if (uvdesc->bLength < subtypelen) {
DPRINTF(("uvideo:"
" truncated CS subtype-0x%x descriptor,"
@@ -1985,7 +2006,10 @@ uvideo_open(void *addr, int flags)
return EIO;
/* XXX select default format */
+ if (vs->vs_default_format == NULL)
+ return EINVAL;
fmt = *vs->vs_default_format;
+
return uvideo_set_format(addr, &fmt);
}
diff -r 04cb149a09ee -r 26f0957ad6f5 sys/dev/usb/uvideoreg.h
--- a/sys/dev/usb/uvideoreg.h Mon Apr 10 15:14:50 2023 +0000
+++ b/sys/dev/usb/uvideoreg.h Mon Apr 10 15:26:56 2023 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: uvideoreg.h,v 1.7 2022/05/14 15:28:59 riastradh Exp $ */
+/* $NetBSD: uvideoreg.h,v 1.8 2023/04/10 15:26:56 mlelstv Exp $ */
/*
* Copyright (c) 2008 Patrick Mahoney
@@ -435,8 +435,9 @@ typedef struct {
uDWord dwMaxVideoFrameBufferSize;
uDWord dwDefaultFrameInterval;
uByte bFrameIntervalType;
+ uvideo_frame_interval_t uFrameInterval;
} UPACKED uvideo_vs_frame_uncompressed_descriptor_t;
-CTASSERT(sizeof(uvideo_vs_frame_uncompressed_descriptor_t) == 26);
+
/* Frame based Format and Frame descriptors. This is for generic
* frame based payloads not covered by other types (e.g, uncompressed
@@ -470,8 +471,9 @@ typedef struct {
uDWord dwDefaultFrameInterval;
uByte bFrameIntervalType;
uDWord dwBytesPerLine;
+ uvideo_frame_interval_t uFrameInterval;
} UPACKED uvideo_frame_frame_based_descriptor_t;
-CTASSERT(sizeof(uvideo_frame_frame_based_descriptor_t) == 26);
+
/* MJPEG format and frame descriptors */
@@ -504,8 +506,9 @@ typedef struct {
uDWord dwMaxVideoFrameBufferSize;
uDWord dwDefaultFrameInterval;
uByte bFrameIntervalType;
+ uvideo_frame_interval_t uFrameInterval;
} UPACKED uvideo_vs_frame_mjpeg_descriptor_t;
-CTASSERT(sizeof(uvideo_vs_frame_mjpeg_descriptor_t) == 26);
+
typedef struct {
uByte bLength;
Home |
Main Index |
Thread Index |
Old Index