0001
0002
0003
0004
0005
0006 #include <linux/init.h>
0007 #include <linux/usb.h>
0008 #include <linux/usb/audio.h>
0009 #include <linux/usb/audio-v2.h>
0010 #include <linux/usb/audio-v3.h>
0011 #include <linux/usb/midi.h>
0012 #include "usbaudio.h"
0013 #include "helper.h"
0014
0015 struct usb_desc_validator {
0016 unsigned char protocol;
0017 unsigned char type;
0018 bool (*func)(const void *p, const struct usb_desc_validator *v);
0019 size_t size;
0020 };
0021
0022 #define UAC_VERSION_ALL (unsigned char)(-1)
0023
0024
0025 static bool validate_uac1_header(const void *p,
0026 const struct usb_desc_validator *v)
0027 {
0028 const struct uac1_ac_header_descriptor *d = p;
0029
0030 return d->bLength >= sizeof(*d) &&
0031 d->bLength >= sizeof(*d) + d->bInCollection;
0032 }
0033
0034
0035 static bool validate_mixer_unit(const void *p,
0036 const struct usb_desc_validator *v)
0037 {
0038 const struct uac_mixer_unit_descriptor *d = p;
0039 size_t len;
0040
0041 if (d->bLength < sizeof(*d) || !d->bNrInPins)
0042 return false;
0043 len = sizeof(*d) + d->bNrInPins;
0044
0045
0046
0047
0048 switch (v->protocol) {
0049 case UAC_VERSION_1:
0050 default:
0051 len += 2 + 1;
0052
0053 len += 1;
0054 break;
0055 case UAC_VERSION_2:
0056 len += 4 + 1;
0057
0058 len += 1 + 1;
0059 break;
0060 case UAC_VERSION_3:
0061 len += 2;
0062
0063 break;
0064 }
0065 return d->bLength >= len;
0066 }
0067
0068
0069 static bool validate_processing_unit(const void *p,
0070 const struct usb_desc_validator *v)
0071 {
0072 const struct uac_processing_unit_descriptor *d = p;
0073 const unsigned char *hdr = p;
0074 size_t len, m;
0075
0076 if (d->bLength < sizeof(*d))
0077 return false;
0078 len = sizeof(*d) + d->bNrInPins;
0079 if (d->bLength < len)
0080 return false;
0081 switch (v->protocol) {
0082 case UAC_VERSION_1:
0083 default:
0084
0085 len += 1 + 2 + 1;
0086 if (d->bLength < len + 1)
0087 return false;
0088 m = hdr[len];
0089 len += 1 + m + 1;
0090 break;
0091 case UAC_VERSION_2:
0092
0093 len += 1 + 4 + 1;
0094 if (v->type == UAC2_PROCESSING_UNIT_V2)
0095 len += 2;
0096 else
0097 len += 1;
0098 len += 1;
0099 break;
0100 case UAC_VERSION_3:
0101
0102 len += 2 + 4;
0103 break;
0104 }
0105 if (d->bLength < len)
0106 return false;
0107
0108 switch (v->protocol) {
0109 case UAC_VERSION_1:
0110 default:
0111 if (v->type == UAC1_EXTENSION_UNIT)
0112 return true;
0113 switch (le16_to_cpu(d->wProcessType)) {
0114 case UAC_PROCESS_UP_DOWNMIX:
0115 case UAC_PROCESS_DOLBY_PROLOGIC:
0116 if (d->bLength < len + 1)
0117 return false;
0118 m = hdr[len];
0119 len += 1 + m * 2;
0120 break;
0121 default:
0122 break;
0123 }
0124 break;
0125 case UAC_VERSION_2:
0126 if (v->type == UAC2_EXTENSION_UNIT_V2)
0127 return true;
0128 switch (le16_to_cpu(d->wProcessType)) {
0129 case UAC2_PROCESS_UP_DOWNMIX:
0130 case UAC2_PROCESS_DOLBY_PROLOCIC:
0131 if (d->bLength < len + 1)
0132 return false;
0133 m = hdr[len];
0134 len += 1 + m * 4;
0135 break;
0136 default:
0137 break;
0138 }
0139 break;
0140 case UAC_VERSION_3:
0141 if (v->type == UAC3_EXTENSION_UNIT) {
0142 len += 2;
0143 break;
0144 }
0145 switch (le16_to_cpu(d->wProcessType)) {
0146 case UAC3_PROCESS_UP_DOWNMIX:
0147 if (d->bLength < len + 1)
0148 return false;
0149 m = hdr[len];
0150 len += 1 + m * 2;
0151 break;
0152 case UAC3_PROCESS_MULTI_FUNCTION:
0153 len += 2 + 4;
0154 break;
0155 default:
0156 break;
0157 }
0158 break;
0159 }
0160 if (d->bLength < len)
0161 return false;
0162
0163 return true;
0164 }
0165
0166
0167 static bool validate_selector_unit(const void *p,
0168 const struct usb_desc_validator *v)
0169 {
0170 const struct uac_selector_unit_descriptor *d = p;
0171 size_t len;
0172
0173 if (d->bLength < sizeof(*d))
0174 return false;
0175 len = sizeof(*d) + d->bNrInPins;
0176 switch (v->protocol) {
0177 case UAC_VERSION_1:
0178 default:
0179 len += 1;
0180 break;
0181 case UAC_VERSION_2:
0182 len += 1 + 1;
0183 break;
0184 case UAC_VERSION_3:
0185 len += 4 + 2;
0186 break;
0187 }
0188 return d->bLength >= len;
0189 }
0190
0191 static bool validate_uac1_feature_unit(const void *p,
0192 const struct usb_desc_validator *v)
0193 {
0194 const struct uac_feature_unit_descriptor *d = p;
0195
0196 if (d->bLength < sizeof(*d) || !d->bControlSize)
0197 return false;
0198
0199 return d->bLength >= sizeof(*d) + d->bControlSize + 1;
0200 }
0201
0202 static bool validate_uac2_feature_unit(const void *p,
0203 const struct usb_desc_validator *v)
0204 {
0205 const struct uac2_feature_unit_descriptor *d = p;
0206
0207 if (d->bLength < sizeof(*d))
0208 return false;
0209
0210 return d->bLength >= sizeof(*d) + 4 + 1;
0211 }
0212
0213 static bool validate_uac3_feature_unit(const void *p,
0214 const struct usb_desc_validator *v)
0215 {
0216 const struct uac3_feature_unit_descriptor *d = p;
0217
0218 if (d->bLength < sizeof(*d))
0219 return false;
0220
0221 return d->bLength >= sizeof(*d) + 4 + 2;
0222 }
0223
0224 static bool validate_midi_out_jack(const void *p,
0225 const struct usb_desc_validator *v)
0226 {
0227 const struct usb_midi_out_jack_descriptor *d = p;
0228
0229 return d->bLength >= sizeof(*d) &&
0230 d->bLength >= sizeof(*d) + d->bNrInputPins * 2;
0231 }
0232
0233 #define FIXED(p, t, s) { .protocol = (p), .type = (t), .size = sizeof(s) }
0234 #define FUNC(p, t, f) { .protocol = (p), .type = (t), .func = (f) }
0235
0236 static const struct usb_desc_validator audio_validators[] = {
0237
0238 FUNC(UAC_VERSION_1, UAC_HEADER, validate_uac1_header),
0239 FIXED(UAC_VERSION_1, UAC_INPUT_TERMINAL,
0240 struct uac_input_terminal_descriptor),
0241 FIXED(UAC_VERSION_1, UAC_OUTPUT_TERMINAL,
0242 struct uac1_output_terminal_descriptor),
0243 FUNC(UAC_VERSION_1, UAC_MIXER_UNIT, validate_mixer_unit),
0244 FUNC(UAC_VERSION_1, UAC_SELECTOR_UNIT, validate_selector_unit),
0245 FUNC(UAC_VERSION_1, UAC_FEATURE_UNIT, validate_uac1_feature_unit),
0246 FUNC(UAC_VERSION_1, UAC1_PROCESSING_UNIT, validate_processing_unit),
0247 FUNC(UAC_VERSION_1, UAC1_EXTENSION_UNIT, validate_processing_unit),
0248
0249
0250 FIXED(UAC_VERSION_2, UAC_HEADER, struct uac2_ac_header_descriptor),
0251 FIXED(UAC_VERSION_2, UAC_INPUT_TERMINAL,
0252 struct uac2_input_terminal_descriptor),
0253 FIXED(UAC_VERSION_2, UAC_OUTPUT_TERMINAL,
0254 struct uac2_output_terminal_descriptor),
0255 FUNC(UAC_VERSION_2, UAC_MIXER_UNIT, validate_mixer_unit),
0256 FUNC(UAC_VERSION_2, UAC_SELECTOR_UNIT, validate_selector_unit),
0257 FUNC(UAC_VERSION_2, UAC_FEATURE_UNIT, validate_uac2_feature_unit),
0258
0259 FUNC(UAC_VERSION_2, UAC2_PROCESSING_UNIT_V2, validate_processing_unit),
0260 FUNC(UAC_VERSION_2, UAC2_EXTENSION_UNIT_V2, validate_processing_unit),
0261 FIXED(UAC_VERSION_2, UAC2_CLOCK_SOURCE,
0262 struct uac_clock_source_descriptor),
0263 FUNC(UAC_VERSION_2, UAC2_CLOCK_SELECTOR, validate_selector_unit),
0264 FIXED(UAC_VERSION_2, UAC2_CLOCK_MULTIPLIER,
0265 struct uac_clock_multiplier_descriptor),
0266
0267
0268
0269 FIXED(UAC_VERSION_2, UAC_HEADER, struct uac3_ac_header_descriptor),
0270 FIXED(UAC_VERSION_3, UAC_INPUT_TERMINAL,
0271 struct uac3_input_terminal_descriptor),
0272 FIXED(UAC_VERSION_3, UAC_OUTPUT_TERMINAL,
0273 struct uac3_output_terminal_descriptor),
0274
0275 FUNC(UAC_VERSION_3, UAC3_MIXER_UNIT, validate_mixer_unit),
0276 FUNC(UAC_VERSION_3, UAC3_SELECTOR_UNIT, validate_selector_unit),
0277 FUNC(UAC_VERSION_3, UAC_FEATURE_UNIT, validate_uac3_feature_unit),
0278
0279 FUNC(UAC_VERSION_3, UAC3_PROCESSING_UNIT, validate_processing_unit),
0280 FUNC(UAC_VERSION_3, UAC3_EXTENSION_UNIT, validate_processing_unit),
0281 FIXED(UAC_VERSION_3, UAC3_CLOCK_SOURCE,
0282 struct uac3_clock_source_descriptor),
0283 FUNC(UAC_VERSION_3, UAC3_CLOCK_SELECTOR, validate_selector_unit),
0284 FIXED(UAC_VERSION_3, UAC3_CLOCK_MULTIPLIER,
0285 struct uac3_clock_multiplier_descriptor),
0286
0287
0288 { }
0289 };
0290
0291 static const struct usb_desc_validator midi_validators[] = {
0292 FIXED(UAC_VERSION_ALL, USB_MS_HEADER,
0293 struct usb_ms_header_descriptor),
0294 FIXED(UAC_VERSION_ALL, USB_MS_MIDI_IN_JACK,
0295 struct usb_midi_in_jack_descriptor),
0296 FUNC(UAC_VERSION_ALL, USB_MS_MIDI_OUT_JACK,
0297 validate_midi_out_jack),
0298 { }
0299 };
0300
0301
0302
0303 static bool validate_desc(unsigned char *hdr, int protocol,
0304 const struct usb_desc_validator *v)
0305 {
0306 if (hdr[1] != USB_DT_CS_INTERFACE)
0307 return true;
0308
0309 for (; v->type; v++) {
0310 if (v->type == hdr[2] &&
0311 (v->protocol == UAC_VERSION_ALL ||
0312 v->protocol == protocol)) {
0313 if (v->func)
0314 return v->func(hdr, v);
0315
0316 return hdr[0] >= v->size;
0317 }
0318 }
0319
0320 return true;
0321 }
0322
0323 bool snd_usb_validate_audio_desc(void *p, int protocol)
0324 {
0325 unsigned char *c = p;
0326 bool valid;
0327
0328 valid = validate_desc(p, protocol, audio_validators);
0329 if (!valid && snd_usb_skip_validation) {
0330 print_hex_dump(KERN_ERR, "USB-audio: buggy audio desc: ",
0331 DUMP_PREFIX_NONE, 16, 1, c, c[0], true);
0332 valid = true;
0333 }
0334 return valid;
0335 }
0336
0337 bool snd_usb_validate_midi_desc(void *p)
0338 {
0339 unsigned char *c = p;
0340 bool valid;
0341
0342 valid = validate_desc(p, UAC_VERSION_1, midi_validators);
0343 if (!valid && snd_usb_skip_validation) {
0344 print_hex_dump(KERN_ERR, "USB-audio: buggy midi desc: ",
0345 DUMP_PREFIX_NONE, 16, 1, c, c[0], true);
0346 valid = true;
0347 }
0348 return valid;
0349 }