sound fixes for 5.0-rc2
A collection of small fixes for USB-audio, HD-audio and cs46xx. The USB-audio fixes are for out-of-bound accesses and a regression in the recent cleanup, while HD-audio fixes are usual device- specific quirks. -----BEGIN PGP SIGNATURE----- iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAlw3TUMOHHRpd2FpQHN1 c2UuZGUACgkQLtJE4w1nLE+sxA/+KzAzchEh/8nlK/8ZQvSN79AA2K2H0c7fdt2v OSXiSNf8tGSxtH57exJf+lV3WPxkjIhtjVP0MSOPs1RShg6rHqdbsd78cRzkD+wk 8eIOHE8Epe3zgIbkBMCymqq1oDmQ5OfRNMdLYsEfjzd6VBbXSqTBmjMXZ8fQ1Pjj fJ+zVIBWBjDBTM/OmvSDalwGEOI0jaYDaR1wuzbU8vmhEmGptWEQklHJVuXXyJPl ZRdPx6FQ3uLWvsQ+4SZi4BR2PYyFs4D4XH9Gq9kdL0fKZsmYf5i07q1zut/aRhcD Hh8ofd8caXIFR3rsYcIeo7xkRmuY8zGlJP5uQmteCKZ8ygC1bX9ukXaH+6BPrV/7 9fEruSajChW6fxTB6qlj3n3kr8lKpzD1X6PuBY9xcDojarx97Q00vw2g55CJygUb meKQY5NSPClJ1kIOuveJ5tr2Jli6aRtB0dw0mGPC4jdQ389DM5VUKK52SBCUFIO8 ROSDB8XDpqS/pJ0iKraZQFxrYUWO4/gHzMCT1otsAM35Lm8JRpApuSCgCHTtTK8P sY7bdAByswKcGd1eA0TZ1sLnqAcUhAcLtk0FWmHozT4Is1mHy+ixdVlfClhDbkUn JNeHFm1M0QP1tuHnJpYuqzCL/2mJbNAXkiJ3X1CK68Qcyigldias2Tv86JcLpkrg CxYQxKc= =f4eE -----END PGP SIGNATURE----- Merge tag 'sound-5.0-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound fixes from Takashi Iwai: "A collection of small fixes for USB-audio, HD-audio and cs46xx. The USB-audio fixes are for out-of-bound accesses and a regression in the recent cleanup, while HD-audio fixes are usual device-specific quirks" * tag 'sound-5.0-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: ALSA: hda/realtek - Disable headset Mic VREF for headset mode of ALC225 ALSA: hda/realtek - Add unplug function into unplug state of Headset Mode for ALC225 ALSA: usb-audio: fix CM6206 register definitions ALSA: cs46xx: Potential NULL dereference in probe ALSA: hda/realtek - Support Dell headset mode for New AIO platform ALSA: usb-audio: Fix an out-of-bound read in create_composite_quirks ALSA: usb-audio: Always check descriptor sizes in parser code ALSA: usb-audio: Check mixer unit descriptors more strictly ALSA: usb-audio: Avoid access before bLength check in build_audio_procunit()
This commit is contained in:
commit
f0ebbe9b18
|
@ -903,6 +903,9 @@ int cs46xx_dsp_proc_done (struct snd_cs46xx *chip)
|
|||
struct dsp_spos_instance * ins = chip->dsp_spos_instance;
|
||||
int i;
|
||||
|
||||
if (!ins)
|
||||
return 0;
|
||||
|
||||
snd_info_free_entry(ins->proc_sym_info_entry);
|
||||
ins->proc_sym_info_entry = NULL;
|
||||
|
||||
|
|
|
@ -4102,6 +4102,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
|
|||
case 0x10ec0295:
|
||||
case 0x10ec0289:
|
||||
case 0x10ec0299:
|
||||
alc_process_coef_fw(codec, alc225_pre_hsmode);
|
||||
alc_process_coef_fw(codec, coef0225);
|
||||
break;
|
||||
case 0x10ec0867:
|
||||
|
@ -5440,6 +5441,13 @@ static void alc_fixup_headset_jack(struct hda_codec *codec,
|
|||
}
|
||||
}
|
||||
|
||||
static void alc_fixup_disable_mic_vref(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
if (action == HDA_FIXUP_ACT_PRE_PROBE)
|
||||
snd_hda_codec_set_pin_target(codec, 0x19, PIN_VREFHIZ);
|
||||
}
|
||||
|
||||
/* for hda_fixup_thinkpad_acpi() */
|
||||
#include "thinkpad_helper.c"
|
||||
|
||||
|
@ -5549,6 +5557,7 @@ enum {
|
|||
ALC293_FIXUP_LENOVO_SPK_NOISE,
|
||||
ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY,
|
||||
ALC255_FIXUP_DELL_SPK_NOISE,
|
||||
ALC225_FIXUP_DISABLE_MIC_VREF,
|
||||
ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
|
||||
ALC295_FIXUP_DISABLE_DAC3,
|
||||
ALC280_FIXUP_HP_HEADSET_MIC,
|
||||
|
@ -6268,6 +6277,12 @@ static const struct hda_fixup alc269_fixups[] = {
|
|||
.chained = true,
|
||||
.chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
|
||||
},
|
||||
[ALC225_FIXUP_DISABLE_MIC_VREF] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc_fixup_disable_mic_vref,
|
||||
.chained = true,
|
||||
.chain_id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE
|
||||
},
|
||||
[ALC225_FIXUP_DELL1_MIC_NO_PRESENCE] = {
|
||||
.type = HDA_FIXUP_VERBS,
|
||||
.v.verbs = (const struct hda_verb[]) {
|
||||
|
@ -6277,7 +6292,7 @@ static const struct hda_fixup alc269_fixups[] = {
|
|||
{}
|
||||
},
|
||||
.chained = true,
|
||||
.chain_id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE
|
||||
.chain_id = ALC225_FIXUP_DISABLE_MIC_VREF
|
||||
},
|
||||
[ALC280_FIXUP_HP_HEADSET_MIC] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
|
@ -6584,6 +6599,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1028, 0x0871, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1028, 0x0872, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1028, 0x0873, "Dell Precision 3930", ALC255_FIXUP_DUMMY_LINEOUT_VERB),
|
||||
SND_PCI_QUIRK(0x1028, 0x0935, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
|
||||
SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
|
||||
|
|
|
@ -246,7 +246,7 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
|
|||
h1 = snd_usb_find_csint_desc(host_iface->extra,
|
||||
host_iface->extralen,
|
||||
NULL, UAC_HEADER);
|
||||
if (!h1) {
|
||||
if (!h1 || h1->bLength < sizeof(*h1)) {
|
||||
dev_err(&dev->dev, "cannot find UAC_HEADER\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -753,8 +753,9 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
|
|||
struct uac_mixer_unit_descriptor *desc)
|
||||
{
|
||||
int mu_channels;
|
||||
void *c;
|
||||
|
||||
if (desc->bLength < 11)
|
||||
if (desc->bLength < sizeof(*desc))
|
||||
return -EINVAL;
|
||||
if (!desc->bNrInPins)
|
||||
return -EINVAL;
|
||||
|
@ -763,6 +764,8 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
|
|||
case UAC_VERSION_1:
|
||||
case UAC_VERSION_2:
|
||||
default:
|
||||
if (desc->bLength < sizeof(*desc) + desc->bNrInPins + 1)
|
||||
return 0; /* no bmControls -> skip */
|
||||
mu_channels = uac_mixer_unit_bNrChannels(desc);
|
||||
break;
|
||||
case UAC_VERSION_3:
|
||||
|
@ -772,7 +775,11 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
|
|||
}
|
||||
|
||||
if (!mu_channels)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
|
||||
c = uac_mixer_unit_bmControls(desc, state->mixer->protocol);
|
||||
if (c - (void *)desc + (mu_channels - 1) / 8 >= desc->bLength)
|
||||
return 0; /* no bmControls -> skip */
|
||||
|
||||
return mu_channels;
|
||||
}
|
||||
|
@ -944,7 +951,7 @@ static int check_input_term(struct mixer_build *state, int id,
|
|||
struct uac_mixer_unit_descriptor *d = p1;
|
||||
|
||||
err = uac_mixer_unit_get_channels(state, d);
|
||||
if (err < 0)
|
||||
if (err <= 0)
|
||||
return err;
|
||||
|
||||
term->channels = err;
|
||||
|
@ -2068,11 +2075,15 @@ static int parse_audio_input_terminal(struct mixer_build *state, int unitid,
|
|||
|
||||
if (state->mixer->protocol == UAC_VERSION_2) {
|
||||
struct uac2_input_terminal_descriptor *d_v2 = raw_desc;
|
||||
if (d_v2->bLength < sizeof(*d_v2))
|
||||
return -EINVAL;
|
||||
control = UAC2_TE_CONNECTOR;
|
||||
term_id = d_v2->bTerminalID;
|
||||
bmctls = le16_to_cpu(d_v2->bmControls);
|
||||
} else if (state->mixer->protocol == UAC_VERSION_3) {
|
||||
struct uac3_input_terminal_descriptor *d_v3 = raw_desc;
|
||||
if (d_v3->bLength < sizeof(*d_v3))
|
||||
return -EINVAL;
|
||||
control = UAC3_TE_INSERTION;
|
||||
term_id = d_v3->bTerminalID;
|
||||
bmctls = le32_to_cpu(d_v3->bmControls);
|
||||
|
@ -2118,7 +2129,7 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid,
|
|||
if (err < 0)
|
||||
continue;
|
||||
/* no bmControls field (e.g. Maya44) -> ignore */
|
||||
if (desc->bLength <= 10 + input_pins)
|
||||
if (!num_outs)
|
||||
continue;
|
||||
err = check_input_term(state, desc->baSourceID[pin], &iterm);
|
||||
if (err < 0)
|
||||
|
@ -2314,7 +2325,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
|
|||
char *name)
|
||||
{
|
||||
struct uac_processing_unit_descriptor *desc = raw_desc;
|
||||
int num_ins = desc->bNrInPins;
|
||||
int num_ins;
|
||||
struct usb_mixer_elem_info *cval;
|
||||
struct snd_kcontrol *kctl;
|
||||
int i, err, nameid, type, len;
|
||||
|
@ -2329,7 +2340,13 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
|
|||
0, NULL, default_value_info
|
||||
};
|
||||
|
||||
if (desc->bLength < 13 || desc->bLength < 13 + num_ins ||
|
||||
if (desc->bLength < 13) {
|
||||
usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
num_ins = desc->bNrInPins;
|
||||
if (desc->bLength < 13 + num_ins ||
|
||||
desc->bLength < num_ins + uac_processing_unit_bControlSize(desc, state->mixer->protocol)) {
|
||||
usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid);
|
||||
return -EINVAL;
|
||||
|
|
|
@ -3326,6 +3326,9 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
|
|||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
.ifnum = -1
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -3369,6 +3372,9 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
|
|||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
.ifnum = -1
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -768,7 +768,7 @@ static int snd_usb_cm6206_boot_quirk(struct usb_device *dev)
|
|||
* REG1: PLL binary search enable, soft mute enable.
|
||||
*/
|
||||
CM6206_REG1_PLLBIN_EN |
|
||||
CM6206_REG1_SOFT_MUTE_EN |
|
||||
CM6206_REG1_SOFT_MUTE_EN,
|
||||
/*
|
||||
* REG2: enable output drivers,
|
||||
* select front channels to the headphone output,
|
||||
|
|
|
@ -596,12 +596,8 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
|
|||
csep = snd_usb_find_desc(alts->extra, alts->extralen, NULL, USB_DT_CS_ENDPOINT);
|
||||
|
||||
if (!csep || csep->bLength < 7 ||
|
||||
csep->bDescriptorSubtype != UAC_EP_GENERAL) {
|
||||
usb_audio_warn(chip,
|
||||
"%u:%d : no or invalid class specific endpoint descriptor\n",
|
||||
iface_no, altsd->bAlternateSetting);
|
||||
return 0;
|
||||
}
|
||||
csep->bDescriptorSubtype != UAC_EP_GENERAL)
|
||||
goto error;
|
||||
|
||||
if (protocol == UAC_VERSION_1) {
|
||||
attributes = csep->bmAttributes;
|
||||
|
@ -609,6 +605,8 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
|
|||
struct uac2_iso_endpoint_descriptor *csep2 =
|
||||
(struct uac2_iso_endpoint_descriptor *) csep;
|
||||
|
||||
if (csep2->bLength < sizeof(*csep2))
|
||||
goto error;
|
||||
attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX;
|
||||
|
||||
/* emulate the endpoint attributes of a v1 device */
|
||||
|
@ -618,12 +616,20 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
|
|||
struct uac3_iso_endpoint_descriptor *csep3 =
|
||||
(struct uac3_iso_endpoint_descriptor *) csep;
|
||||
|
||||
if (csep3->bLength < sizeof(*csep3))
|
||||
goto error;
|
||||
/* emulate the endpoint attributes of a v1 device */
|
||||
if (le32_to_cpu(csep3->bmControls) & UAC2_CONTROL_PITCH)
|
||||
attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
|
||||
}
|
||||
|
||||
return attributes;
|
||||
|
||||
error:
|
||||
usb_audio_warn(chip,
|
||||
"%u:%d : no or invalid class specific endpoint descriptor\n",
|
||||
iface_no, altsd->bAlternateSetting);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* find an input terminal descriptor (either UAC1 or UAC2) with the given
|
||||
|
@ -631,13 +637,17 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
|
|||
*/
|
||||
static void *
|
||||
snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface,
|
||||
int terminal_id)
|
||||
int terminal_id, bool uac23)
|
||||
{
|
||||
struct uac2_input_terminal_descriptor *term = NULL;
|
||||
size_t minlen = uac23 ? sizeof(struct uac2_input_terminal_descriptor) :
|
||||
sizeof(struct uac_input_terminal_descriptor);
|
||||
|
||||
while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
|
||||
ctrl_iface->extralen,
|
||||
term, UAC_INPUT_TERMINAL))) {
|
||||
if (term->bLength < minlen)
|
||||
continue;
|
||||
if (term->bTerminalID == terminal_id)
|
||||
return term;
|
||||
}
|
||||
|
@ -655,7 +665,8 @@ snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface,
|
|||
while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
|
||||
ctrl_iface->extralen,
|
||||
term, UAC_OUTPUT_TERMINAL))) {
|
||||
if (term->bTerminalID == terminal_id)
|
||||
if (term->bLength >= sizeof(*term) &&
|
||||
term->bTerminalID == terminal_id)
|
||||
return term;
|
||||
}
|
||||
|
||||
|
@ -729,7 +740,8 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
|
|||
format = le16_to_cpu(as->wFormatTag); /* remember the format value */
|
||||
|
||||
iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
|
||||
as->bTerminalLink);
|
||||
as->bTerminalLink,
|
||||
false);
|
||||
if (iterm) {
|
||||
num_channels = iterm->bNrChannels;
|
||||
chconfig = le16_to_cpu(iterm->wChannelConfig);
|
||||
|
@ -764,7 +776,8 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
|
|||
* to extract the clock
|
||||
*/
|
||||
input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
|
||||
as->bTerminalLink);
|
||||
as->bTerminalLink,
|
||||
true);
|
||||
if (input_term) {
|
||||
clock = input_term->bCSourceID;
|
||||
if (!chconfig && (num_channels == input_term->bNrChannels))
|
||||
|
@ -998,7 +1011,8 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
|
|||
* to extract the clock
|
||||
*/
|
||||
input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
|
||||
as->bTerminalLink);
|
||||
as->bTerminalLink,
|
||||
true);
|
||||
if (input_term) {
|
||||
clock = input_term->bCSourceID;
|
||||
goto found_clock;
|
||||
|
|
Loading…
Reference in New Issue