summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/usb/clock.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index 8f85200292f3..842ba5b801ea 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -36,6 +36,12 @@ union uac23_clock_multiplier_desc {
struct uac_clock_multiplier_descriptor v3;
};
+/* check whether the descriptor bLength has the minimal length */
+#define DESC_LENGTH_CHECK(p, proto) \
+ ((proto) == UAC_VERSION_3 ? \
+ ((p)->v3.bLength >= sizeof((p)->v3)) : \
+ ((p)->v2.bLength >= sizeof((p)->v2)))
+
#define GET_VAL(p, proto, field) \
((proto) == UAC_VERSION_3 ? (p)->v3.field : (p)->v2.field)
@@ -58,6 +64,8 @@ static bool validate_clock_source(void *p, int id, int proto)
{
union uac23_clock_source_desc *cs = p;
+ if (!DESC_LENGTH_CHECK(cs, proto))
+ return false;
return GET_VAL(cs, proto, bClockID) == id;
}
@@ -65,13 +73,27 @@ static bool validate_clock_selector(void *p, int id, int proto)
{
union uac23_clock_selector_desc *cs = p;
- return GET_VAL(cs, proto, bClockID) == id;
+ if (!DESC_LENGTH_CHECK(cs, proto))
+ return false;
+ if (GET_VAL(cs, proto, bClockID) != id)
+ return false;
+ /* additional length check for baCSourceID array (in bNrInPins size)
+ * and two more fields (which sizes depend on the protocol)
+ */
+ if (proto == UAC_VERSION_3)
+ return cs->v3.bLength >= sizeof(cs->v3) + cs->v3.bNrInPins +
+ 4 /* bmControls */ + 2 /* wCSelectorDescrStr */;
+ else
+ return cs->v2.bLength >= sizeof(cs->v2) + cs->v2.bNrInPins +
+ 1 /* bmControls */ + 1 /* iClockSelector */;
}
static bool validate_clock_multiplier(void *p, int id, int proto)
{
union uac23_clock_multiplier_desc *cs = p;
+ if (!DESC_LENGTH_CHECK(cs, proto))
+ return false;
return GET_VAL(cs, proto, bClockID) == id;
}