[alsa-devel] [PATCH 1/2] ALSA: usb-audio: Fix incorrect size check for processing/extension units
The recently introduced unit descriptor validation had some bug for processing and extension units, it counts a bControlSize byte twice so it expected a bigger size than it should have been. This seems resulting in a probe error on a few devices.
Fix the calculation for proper checks of PU and EU.
Fixes: 57f8770620e9 ("ALSA: usb-audio: More validations of descriptor units") Cc: stable@vger.kernel.org Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/usb/validate.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/sound/usb/validate.c b/sound/usb/validate.c index a5e584b60dcd..389e8657434a 100644 --- a/sound/usb/validate.c +++ b/sound/usb/validate.c @@ -81,9 +81,9 @@ static bool validate_processing_unit(const void *p, switch (v->protocol) { case UAC_VERSION_1: default: - /* bNrChannels, wChannelConfig, iChannelNames, bControlSize */ - len += 1 + 2 + 1 + 1; - if (d->bLength < len) /* bControlSize */ + /* bNrChannels, wChannelConfig, iChannelNames */ + len += 1 + 2 + 1; + if (d->bLength < len + 1) /* bControlSize */ return false; m = hdr[len]; len += 1 + m + 1; /* bControlSize, bmControls, iProcessing */
The unit descriptor validation may lead to a probe error when the device provides a buggy descriptor or the validator detected incorrectly. For identifying such an error and band-aiding, give a new module option, skip_validation. With this option, the driver ignores the validation errors with the hexdump of the unit descriptor, so we can check it in a bit more details.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/usb/card.c | 3 +++ sound/usb/usbaudio.h | 1 + sound/usb/validate.c | 23 ++++++++++++++++++++--- 3 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/sound/usb/card.c b/sound/usb/card.c index db91dc76cc91..9f743ebae615 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -74,6 +74,7 @@ static bool autoclock = true; static char *quirk_alias[SNDRV_CARDS];
bool snd_usb_use_vmalloc = true; +bool snd_usb_skip_validation;
module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for the USB audio adapter."); @@ -96,6 +97,8 @@ module_param_array(quirk_alias, charp, NULL, 0444); MODULE_PARM_DESC(quirk_alias, "Quirk aliases, e.g. 0123abcd:5678beef."); module_param_named(use_vmalloc, snd_usb_use_vmalloc, bool, 0444); MODULE_PARM_DESC(use_vmalloc, "Use vmalloc for PCM intermediate buffers (default: yes)."); +module_param_named(skip_validation, snd_usb_skip_validation, bool, 0444); +MODULE_PARM_DESC(skip_validation, "Skip unit descriptor validation (default: no).");
/* * we keep the snd_usb_audio_t instances by ourselves for merging diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index feb30f9c1716..ff3cbf653de8 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -120,5 +120,6 @@ int snd_usb_lock_shutdown(struct snd_usb_audio *chip); void snd_usb_unlock_shutdown(struct snd_usb_audio *chip);
extern bool snd_usb_use_vmalloc; +extern bool snd_usb_skip_validation;
#endif /* __USBAUDIO_H */ diff --git a/sound/usb/validate.c b/sound/usb/validate.c index 389e8657434a..36ae78c3da3d 100644 --- a/sound/usb/validate.c +++ b/sound/usb/validate.c @@ -322,11 +322,28 @@ static bool validate_desc(unsigned char *hdr, int protocol,
bool snd_usb_validate_audio_desc(void *p, int protocol) { - return validate_desc(p, protocol, audio_validators); + unsigned char *c = p; + bool valid; + + valid = validate_desc(p, protocol, audio_validators); + if (!valid && snd_usb_skip_validation) { + print_hex_dump(KERN_ERR, "USB-audio: buggy audio desc: ", + DUMP_PREFIX_NONE, 16, 1, c, c[0], true); + valid = true; + } + return valid; }
bool snd_usb_validate_midi_desc(void *p) { - return validate_desc(p, UAC_VERSION_1, midi_validators); + unsigned char *c = p; + bool valid; + + valid = validate_desc(p, UAC_VERSION_1, midi_validators); + if (!valid && snd_usb_skip_validation) { + print_hex_dump(KERN_ERR, "USB-audio: buggy midi desc: ", + DUMP_PREFIX_NONE, 16, 1, c, c[0], true); + valid = true; + } + return valid; } -
participants (1)
-
Takashi Iwai