1 // SPDX-License-Identifier: GPL-2.0-or-later 2 // 3 // Validation of USB-audio class descriptors 4 // 5 6 #include <linux/init.h> 7 #include <linux/usb.h> 8 #include <linux/usb/audio.h> 9 #include <linux/usb/audio-v2.h> 10 #include <linux/usb/audio-v3.h> 11 #include <linux/usb/midi.h> 12 #include "usbaudio.h" 13 #include "helper.h" 14 15 struct usb_desc_validator { 16 unsigned char protocol; 17 unsigned char type; 18 bool (*func)(const void *p, const struct usb_desc_validator *v); 19 size_t size; 20 }; 21 22 #define UAC_VERSION_ALL (unsigned char)(-1) 23 24 /* UAC1 only */ 25 static bool validate_uac1_header(const void *p, 26 const struct usb_desc_validator *v) 27 { 28 const struct uac1_ac_header_descriptor *d = p; 29 30 return d->bLength >= sizeof(*d) && 31 d->bLength >= sizeof(*d) + d->bInCollection; 32 } 33 34 /* for mixer unit; covering all UACs */ 35 static bool validate_mixer_unit(const void *p, 36 const struct usb_desc_validator *v) 37 { 38 const struct uac_mixer_unit_descriptor *d = p; 39 size_t len; 40 41 if (d->bLength < sizeof(*d) || !d->bNrInPins) 42 return false; 43 len = sizeof(*d) + d->bNrInPins; 44 /* We can't determine the bitmap size only from this unit descriptor, 45 * so just check with the remaining length. 46 * The actual bitmap is checked at mixer unit parser. 47 */ 48 switch (v->protocol) { 49 case UAC_VERSION_1: 50 default: 51 len += 2 + 1; /* wChannelConfig, iChannelNames */ 52 /* bmControls[n*m] */ 53 len += 1; /* iMixer */ 54 break; 55 case UAC_VERSION_2: 56 len += 4 + 1; /* bmChannelConfig, iChannelNames */ 57 /* bmMixerControls[n*m] */ 58 len += 1 + 1; /* bmControls, iMixer */ 59 break; 60 case UAC_VERSION_3: 61 len += 2; /* wClusterDescrID */ 62 /* bmMixerControls[n*m] */ 63 break; 64 } 65 return d->bLength >= len; 66 } 67 68 /* both for processing and extension units; covering all UACs */ 69 static bool validate_processing_unit(const void *p, 70 const struct usb_desc_validator *v) 71 { 72 const struct uac_processing_unit_descriptor *d = p; 73 const unsigned char *hdr = p; 74 size_t len, m; 75 76 if (d->bLength < sizeof(*d)) 77 return false; 78 len = sizeof(*d) + d->bNrInPins; 79 if (d->bLength < len) 80 return false; 81 switch (v->protocol) { 82 case UAC_VERSION_1: 83 default: 84 /* bNrChannels, wChannelConfig, iChannelNames */ 85 len += 1 + 2 + 1; 86 if (d->bLength < len + 1) /* bControlSize */ 87 return false; 88 m = hdr[len]; 89 len += 1 + m + 1; /* bControlSize, bmControls, iProcessing */ 90 break; 91 case UAC_VERSION_2: 92 /* bNrChannels, bmChannelConfig, iChannelNames */ 93 len += 1 + 4 + 1; 94 if (v->type == UAC2_PROCESSING_UNIT_V2) 95 len += 2; /* bmControls -- 2 bytes for PU */ 96 else 97 len += 1; /* bmControls -- 1 byte for EU */ 98 len += 1; /* iProcessing */ 99 break; 100 case UAC_VERSION_3: 101 /* wProcessingDescrStr, bmControls */ 102 len += 2 + 4; 103 break; 104 } 105 if (d->bLength < len) 106 return false; 107 108 switch (v->protocol) { 109 case UAC_VERSION_1: 110 default: 111 if (v->type == UAC1_EXTENSION_UNIT) 112 return true; /* OK */ 113 switch (le16_to_cpu(d->wProcessType)) { 114 case UAC_PROCESS_UP_DOWNMIX: 115 case UAC_PROCESS_DOLBY_PROLOGIC: 116 if (d->bLength < len + 1) /* bNrModes */ 117 return false; 118 m = hdr[len]; 119 len += 1 + m * 2; /* bNrModes, waModes(n) */ 120 break; 121 default: 122 break; 123 } 124 break; 125 case UAC_VERSION_2: 126 if (v->type == UAC2_EXTENSION_UNIT_V2) 127 return true; /* OK */ 128 switch (le16_to_cpu(d->wProcessType)) { 129 case UAC2_PROCESS_UP_DOWNMIX: 130 case UAC2_PROCESS_DOLBY_PROLOCIC: /* SiC! */ 131 if (d->bLength < len + 1) /* bNrModes */ 132 return false; 133 m = hdr[len]; 134 len += 1 + m * 4; /* bNrModes, daModes(n) */ 135 break; 136 default: 137 break; 138 } 139 break; 140 case UAC_VERSION_3: 141 if (v->type == UAC3_EXTENSION_UNIT) { 142 len += 2; /* wClusterDescrID */ 143 break; 144 } 145 switch (le16_to_cpu(d->wProcessType)) { 146 case UAC3_PROCESS_UP_DOWNMIX: 147 if (d->bLength < len + 1) /* bNrModes */ 148 return false; 149 m = hdr[len]; 150 len += 1 + m * 2; /* bNrModes, waClusterDescrID(n) */ 151 break; 152 case UAC3_PROCESS_MULTI_FUNCTION: 153 len += 2 + 4; /* wClusterDescrID, bmAlgorighms */ 154 break; 155 default: 156 break; 157 } 158 break; 159 } 160 if (d->bLength < len) 161 return false; 162 163 return true; 164 } 165 166 /* both for selector and clock selector units; covering all UACs */ 167 static bool validate_selector_unit(const void *p, 168 const struct usb_desc_validator *v) 169 { 170 const struct uac_selector_unit_descriptor *d = p; 171 size_t len; 172 173 if (d->bLength < sizeof(*d)) 174 return false; 175 len = sizeof(*d) + d->bNrInPins; 176 switch (v->protocol) { 177 case UAC_VERSION_1: 178 default: 179 len += 1; /* iSelector */ 180 break; 181 case UAC_VERSION_2: 182 len += 1 + 1; /* bmControls, iSelector */ 183 break; 184 case UAC_VERSION_3: 185 len += 4 + 2; /* bmControls, wSelectorDescrStr */ 186 break; 187 } 188 return d->bLength >= len; 189 } 190 191 static bool validate_uac1_feature_unit(const void *p, 192 const struct usb_desc_validator *v) 193 { 194 const struct uac_feature_unit_descriptor *d = p; 195 196 if (d->bLength < sizeof(*d) || !d->bControlSize) 197 return false; 198 /* at least bmaControls(0) for master channel + iFeature */ 199 return d->bLength >= sizeof(*d) + d->bControlSize + 1; 200 } 201 202 static bool validate_uac2_feature_unit(const void *p, 203 const struct usb_desc_validator *v) 204 { 205 const struct uac2_feature_unit_descriptor *d = p; 206 207 if (d->bLength < sizeof(*d)) 208 return false; 209 /* at least bmaControls(0) for master channel + iFeature */ 210 return d->bLength >= sizeof(*d) + 4 + 1; 211 } 212 213 static bool validate_uac3_feature_unit(const void *p, 214 const struct usb_desc_validator *v) 215 { 216 const struct uac3_feature_unit_descriptor *d = p; 217 218 if (d->bLength < sizeof(*d)) 219 return false; 220 /* at least bmaControls(0) for master channel + wFeatureDescrStr */ 221 return d->bLength >= sizeof(*d) + 4 + 2; 222 } 223 224 static bool validate_midi_out_jack(const void *p, 225 const struct usb_desc_validator *v) 226 { 227 const struct usb_midi_out_jack_descriptor *d = p; 228 229 return d->bLength >= sizeof(*d) && 230 d->bLength >= sizeof(*d) + d->bNrInputPins * 2; 231 } 232 233 #define FIXED(p, t, s) { .protocol = (p), .type = (t), .size = sizeof(s) } 234 #define FUNC(p, t, f) { .protocol = (p), .type = (t), .func = (f) } 235 236 static const struct usb_desc_validator audio_validators[] = { 237 /* UAC1 */ 238 FUNC(UAC_VERSION_1, UAC_HEADER, validate_uac1_header), 239 FIXED(UAC_VERSION_1, UAC_INPUT_TERMINAL, 240 struct uac_input_terminal_descriptor), 241 FIXED(UAC_VERSION_1, UAC_OUTPUT_TERMINAL, 242 struct uac1_output_terminal_descriptor), 243 FUNC(UAC_VERSION_1, UAC_MIXER_UNIT, validate_mixer_unit), 244 FUNC(UAC_VERSION_1, UAC_SELECTOR_UNIT, validate_selector_unit), 245 FUNC(UAC_VERSION_1, UAC_FEATURE_UNIT, validate_uac1_feature_unit), 246 FUNC(UAC_VERSION_1, UAC1_PROCESSING_UNIT, validate_processing_unit), 247 FUNC(UAC_VERSION_1, UAC1_EXTENSION_UNIT, validate_processing_unit), 248 249 /* UAC2 */ 250 FIXED(UAC_VERSION_2, UAC_HEADER, struct uac2_ac_header_descriptor), 251 FIXED(UAC_VERSION_2, UAC_INPUT_TERMINAL, 252 struct uac2_input_terminal_descriptor), 253 FIXED(UAC_VERSION_2, UAC_OUTPUT_TERMINAL, 254 struct uac2_output_terminal_descriptor), 255 FUNC(UAC_VERSION_2, UAC_MIXER_UNIT, validate_mixer_unit), 256 FUNC(UAC_VERSION_2, UAC_SELECTOR_UNIT, validate_selector_unit), 257 FUNC(UAC_VERSION_2, UAC_FEATURE_UNIT, validate_uac2_feature_unit), 258 /* UAC_VERSION_2, UAC2_EFFECT_UNIT: not implemented yet */ 259 FUNC(UAC_VERSION_2, UAC2_PROCESSING_UNIT_V2, validate_processing_unit), 260 FUNC(UAC_VERSION_2, UAC2_EXTENSION_UNIT_V2, validate_processing_unit), 261 FIXED(UAC_VERSION_2, UAC2_CLOCK_SOURCE, 262 struct uac_clock_source_descriptor), 263 FUNC(UAC_VERSION_2, UAC2_CLOCK_SELECTOR, validate_selector_unit), 264 FIXED(UAC_VERSION_2, UAC2_CLOCK_MULTIPLIER, 265 struct uac_clock_multiplier_descriptor), 266 /* UAC_VERSION_2, UAC2_SAMPLE_RATE_CONVERTER: not implemented yet */ 267 268 /* UAC3 */ 269 FIXED(UAC_VERSION_2, UAC_HEADER, struct uac3_ac_header_descriptor), 270 FIXED(UAC_VERSION_3, UAC_INPUT_TERMINAL, 271 struct uac3_input_terminal_descriptor), 272 FIXED(UAC_VERSION_3, UAC_OUTPUT_TERMINAL, 273 struct uac3_output_terminal_descriptor), 274 /* UAC_VERSION_3, UAC3_EXTENDED_TERMINAL: not implemented yet */ 275 FUNC(UAC_VERSION_3, UAC3_MIXER_UNIT, validate_mixer_unit), 276 FUNC(UAC_VERSION_3, UAC3_SELECTOR_UNIT, validate_selector_unit), 277 FUNC(UAC_VERSION_3, UAC_FEATURE_UNIT, validate_uac3_feature_unit), 278 /* UAC_VERSION_3, UAC3_EFFECT_UNIT: not implemented yet */ 279 FUNC(UAC_VERSION_3, UAC3_PROCESSING_UNIT, validate_processing_unit), 280 FUNC(UAC_VERSION_3, UAC3_EXTENSION_UNIT, validate_processing_unit), 281 FIXED(UAC_VERSION_3, UAC3_CLOCK_SOURCE, 282 struct uac3_clock_source_descriptor), 283 FUNC(UAC_VERSION_3, UAC3_CLOCK_SELECTOR, validate_selector_unit), 284 FIXED(UAC_VERSION_3, UAC3_CLOCK_MULTIPLIER, 285 struct uac3_clock_multiplier_descriptor), 286 /* UAC_VERSION_3, UAC3_SAMPLE_RATE_CONVERTER: not implemented yet */ 287 /* UAC_VERSION_3, UAC3_CONNECTORS: not implemented yet */ 288 { } /* terminator */ 289 }; 290 291 static const struct usb_desc_validator midi_validators[] = { 292 FIXED(UAC_VERSION_ALL, USB_MS_HEADER, 293 struct usb_ms_header_descriptor), 294 FIXED(UAC_VERSION_ALL, USB_MS_MIDI_IN_JACK, 295 struct usb_midi_in_jack_descriptor), 296 FUNC(UAC_VERSION_ALL, USB_MS_MIDI_OUT_JACK, 297 validate_midi_out_jack), 298 { } /* terminator */ 299 }; 300 301 302 /* Validate the given unit descriptor, return true if it's OK */ 303 static bool validate_desc(unsigned char *hdr, int protocol, 304 const struct usb_desc_validator *v) 305 { 306 if (hdr[1] != USB_DT_CS_INTERFACE) 307 return true; /* don't care */ 308 309 for (; v->type; v++) { 310 if (v->type == hdr[2] && 311 (v->protocol == UAC_VERSION_ALL || 312 v->protocol == protocol)) { 313 if (v->func) 314 return v->func(hdr, v); 315 /* check for the fixed size */ 316 return hdr[0] >= v->size; 317 } 318 } 319 320 return true; /* not matching, skip validation */ 321 } 322 323 bool snd_usb_validate_audio_desc(void *p, int protocol) 324 { 325 unsigned char *c = p; 326 bool valid; 327 328 valid = validate_desc(p, protocol, audio_validators); 329 if (!valid && snd_usb_skip_validation) { 330 print_hex_dump(KERN_ERR, "USB-audio: buggy audio desc: ", 331 DUMP_PREFIX_NONE, 16, 1, c, c[0], true); 332 valid = true; 333 } 334 return valid; 335 } 336 337 bool snd_usb_validate_midi_desc(void *p) 338 { 339 unsigned char *c = p; 340 bool valid; 341 342 valid = validate_desc(p, UAC_VERSION_1, midi_validators); 343 if (!valid && snd_usb_skip_validation) { 344 print_hex_dump(KERN_ERR, "USB-audio: buggy midi desc: ", 345 DUMP_PREFIX_NONE, 16, 1, c, c[0], true); 346 valid = true; 347 } 348 return valid; 349 } 350
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.