1 // SPDX-License-Identifier: GPL-2.0-or-later 1 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 stru 19 size_t size; 20 }; 21 22 #define UAC_VERSION_ALL (unsigned char 23 24 /* UAC1 only */ 25 static bool validate_uac1_header(const void *p 26 const struct 27 { 28 const struct uac1_ac_header_descriptor 29 30 return d->bLength >= sizeof(*d) && 31 d->bLength >= sizeof(*d) + d-> 32 } 33 34 /* for mixer unit; covering all UACs */ 35 static bool validate_mixer_unit(const void *p, 36 const struct u 37 { 38 const struct uac_mixer_unit_descriptor 39 size_t len; 40 41 if (d->bLength < sizeof(*d) || !d->bNr 42 return false; 43 len = sizeof(*d) + d->bNrInPins; 44 /* We can't determine the bitmap size 45 * so just check with the remaining le 46 * The actual bitmap is checked at mix 47 */ 48 switch (v->protocol) { 49 case UAC_VERSION_1: 50 default: 51 len += 2 + 1; /* wChannelConfi 52 /* bmControls[n*m] */ 53 len += 1; /* iMixer */ 54 break; 55 case UAC_VERSION_2: 56 len += 4 + 1; /* bmChannelConf 57 /* bmMixerControls[n*m] */ 58 len += 1 + 1; /* bmControls, i 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; co 69 static bool validate_processing_unit(const voi 70 const str 71 { 72 const struct uac_processing_unit_descr 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 85 len += 1 + 2 + 1; 86 if (d->bLength < len + 1) /* b 87 return false; 88 m = hdr[len]; 89 len += 1 + m + 1; /* bControlS 90 break; 91 case UAC_VERSION_2: 92 /* bNrChannels, bmChannelConfi 93 len += 1 + 4 + 1; 94 if (v->type == UAC2_PROCESSING 95 len += 2; /* bmControl 96 else 97 len += 1; /* bmControl 98 len += 1; /* iProcessing */ 99 break; 100 case UAC_VERSION_3: 101 /* wProcessingDescrStr, bmCont 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_ 112 return true; /* OK */ 113 switch (le16_to_cpu(d->wProces 114 case UAC_PROCESS_UP_DOWNMIX: 115 case UAC_PROCESS_DOLBY_PROLOGI 116 if (d->bLength < len + 117 return false; 118 m = hdr[len]; 119 len += 1 + m * 2; /* b 120 break; 121 default: 122 break; 123 } 124 break; 125 case UAC_VERSION_2: 126 if (v->type == UAC2_EXTENSION_ 127 return true; /* OK */ 128 switch (le16_to_cpu(d->wProces 129 case UAC2_PROCESS_UP_DOWNMIX: 130 case UAC2_PROCESS_DOLBY_PROLOC 131 if (d->bLength < len + 132 return false; 133 m = hdr[len]; 134 len += 1 + m * 4; /* b 135 break; 136 default: 137 break; 138 } 139 break; 140 case UAC_VERSION_3: 141 if (v->type == UAC3_EXTENSION_ 142 len += 2; /* wClusterD 143 break; 144 } 145 switch (le16_to_cpu(d->wProces 146 case UAC3_PROCESS_UP_DOWNMIX: 147 if (d->bLength < len + 148 return false; 149 m = hdr[len]; 150 len += 1 + m * 2; /* b 151 break; 152 case UAC3_PROCESS_MULTI_FUNCTI 153 len += 2 + 4; /* wClus 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; 167 static bool validate_selector_unit(const void 168 const struc 169 { 170 const struct uac_selector_unit_descrip 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, i 183 break; 184 case UAC_VERSION_3: 185 len += 4 + 2; /* bmControls, w 186 break; 187 } 188 return d->bLength >= len; 189 } 190 191 static bool validate_uac1_feature_unit(const v 192 const s 193 { 194 const struct uac_feature_unit_descript 195 196 if (d->bLength < sizeof(*d) || !d->bCo 197 return false; 198 /* at least bmaControls(0) for master 199 return d->bLength >= sizeof(*d) + d->b 200 } 201 202 static bool validate_uac2_feature_unit(const v 203 const s 204 { 205 const struct uac2_feature_unit_descrip 206 207 if (d->bLength < sizeof(*d)) 208 return false; 209 /* at least bmaControls(0) for master 210 return d->bLength >= sizeof(*d) + 4 + 211 } 212 213 static bool validate_uac3_feature_unit(const v 214 const s 215 { 216 const struct uac3_feature_unit_descrip 217 218 if (d->bLength < sizeof(*d)) 219 return false; 220 /* at least bmaControls(0) for master 221 return d->bLength >= sizeof(*d) + 4 + 222 } 223 224 static bool validate_midi_out_jack(const void 225 const struc 226 { 227 const struct usb_midi_out_jack_descrip 228 229 return d->bLength >= sizeof(*d) && 230 d->bLength >= sizeof(*d) + d-> 231 } 232 233 #define FIXED(p, t, s) { .protocol = (p), .typ 234 #define FUNC(p, t, f) { .protocol = (p), .type 235 236 static const struct usb_desc_validator audio_v 237 /* UAC1 */ 238 FUNC(UAC_VERSION_1, UAC_HEADER, valida 239 FIXED(UAC_VERSION_1, UAC_INPUT_TERMINA 240 struct uac_input_terminal_descri 241 FIXED(UAC_VERSION_1, UAC_OUTPUT_TERMIN 242 struct uac1_output_terminal_desc 243 FUNC(UAC_VERSION_1, UAC_MIXER_UNIT, va 244 FUNC(UAC_VERSION_1, UAC_SELECTOR_UNIT, 245 FUNC(UAC_VERSION_1, UAC_FEATURE_UNIT, 246 FUNC(UAC_VERSION_1, UAC1_PROCESSING_UN 247 FUNC(UAC_VERSION_1, UAC1_EXTENSION_UNI 248 249 /* UAC2 */ 250 FIXED(UAC_VERSION_2, UAC_HEADER, struc 251 FIXED(UAC_VERSION_2, UAC_INPUT_TERMINA 252 struct uac2_input_terminal_descr 253 FIXED(UAC_VERSION_2, UAC_OUTPUT_TERMIN 254 struct uac2_output_terminal_desc 255 FUNC(UAC_VERSION_2, UAC_MIXER_UNIT, va 256 FUNC(UAC_VERSION_2, UAC_SELECTOR_UNIT, 257 FUNC(UAC_VERSION_2, UAC_FEATURE_UNIT, 258 /* UAC_VERSION_2, UAC2_EFFECT_UNIT: no 259 FUNC(UAC_VERSION_2, UAC2_PROCESSING_UN 260 FUNC(UAC_VERSION_2, UAC2_EXTENSION_UNI 261 FIXED(UAC_VERSION_2, UAC2_CLOCK_SOURCE 262 struct uac_clock_source_descript 263 FUNC(UAC_VERSION_2, UAC2_CLOCK_SELECTO 264 FIXED(UAC_VERSION_2, UAC2_CLOCK_MULTIP 265 struct uac_clock_multiplier_desc 266 /* UAC_VERSION_2, UAC2_SAMPLE_RATE_CON 267 268 /* UAC3 */ 269 FIXED(UAC_VERSION_2, UAC_HEADER, struc 270 FIXED(UAC_VERSION_3, UAC_INPUT_TERMINA 271 struct uac3_input_terminal_descr 272 FIXED(UAC_VERSION_3, UAC_OUTPUT_TERMIN 273 struct uac3_output_terminal_desc 274 /* UAC_VERSION_3, UAC3_EXTENDED_TERMIN 275 FUNC(UAC_VERSION_3, UAC3_MIXER_UNIT, v 276 FUNC(UAC_VERSION_3, UAC3_SELECTOR_UNIT 277 FUNC(UAC_VERSION_3, UAC_FEATURE_UNIT, 278 /* UAC_VERSION_3, UAC3_EFFECT_UNIT: n 279 FUNC(UAC_VERSION_3, UAC3_PROCESSING_UN 280 FUNC(UAC_VERSION_3, UAC3_EXTENSION_UNI 281 FIXED(UAC_VERSION_3, UAC3_CLOCK_SOURCE 282 struct uac3_clock_source_descrip 283 FUNC(UAC_VERSION_3, UAC3_CLOCK_SELECTO 284 FIXED(UAC_VERSION_3, UAC3_CLOCK_MULTIP 285 struct uac3_clock_multiplier_des 286 /* UAC_VERSION_3, UAC3_SAMPLE_RATE_CON 287 /* UAC_VERSION_3, UAC3_CONNECTORS: not 288 { } /* terminator */ 289 }; 290 291 static const struct usb_desc_validator midi_va 292 FIXED(UAC_VERSION_ALL, USB_MS_HEADER, 293 struct usb_ms_header_descriptor) 294 FIXED(UAC_VERSION_ALL, USB_MS_MIDI_IN_ 295 struct usb_midi_in_jack_descript 296 FUNC(UAC_VERSION_ALL, USB_MS_MIDI_OUT_ 297 validate_midi_out_jack), 298 { } /* terminator */ 299 }; 300 301 302 /* Validate the given unit descriptor, return 303 static bool validate_desc(unsigned char *hdr, 304 const struct usb_des 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_VERSIO 312 v->protocol == protocol)) 313 if (v->func) 314 return v->func 315 /* check for the fixed 316 return hdr[0] >= v->si 317 } 318 } 319 320 return true; /* not matching, skip val 321 } 322 323 bool snd_usb_validate_audio_desc(void *p, int 324 { 325 unsigned char *c = p; 326 bool valid; 327 328 valid = validate_desc(p, protocol, aud 329 if (!valid && snd_usb_skip_validation) 330 print_hex_dump(KERN_ERR, "USB- 331 DUMP_PREFIX_NON 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 343 if (!valid && snd_usb_skip_validation) 344 print_hex_dump(KERN_ERR, "USB- 345 DUMP_PREFIX_NON 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.