Commit f0ebbe9b authored by Linus Torvalds's avatar Linus Torvalds

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()
parents e7446be4 d1dd4211
...@@ -903,6 +903,9 @@ int cs46xx_dsp_proc_done (struct snd_cs46xx *chip) ...@@ -903,6 +903,9 @@ int cs46xx_dsp_proc_done (struct snd_cs46xx *chip)
struct dsp_spos_instance * ins = chip->dsp_spos_instance; struct dsp_spos_instance * ins = chip->dsp_spos_instance;
int i; int i;
if (!ins)
return 0;
snd_info_free_entry(ins->proc_sym_info_entry); snd_info_free_entry(ins->proc_sym_info_entry);
ins->proc_sym_info_entry = NULL; ins->proc_sym_info_entry = NULL;
......
...@@ -4102,6 +4102,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) ...@@ -4102,6 +4102,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
case 0x10ec0295: case 0x10ec0295:
case 0x10ec0289: case 0x10ec0289:
case 0x10ec0299: case 0x10ec0299:
alc_process_coef_fw(codec, alc225_pre_hsmode);
alc_process_coef_fw(codec, coef0225); alc_process_coef_fw(codec, coef0225);
break; break;
case 0x10ec0867: case 0x10ec0867:
...@@ -5440,6 +5441,13 @@ static void alc_fixup_headset_jack(struct hda_codec *codec, ...@@ -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() */ /* for hda_fixup_thinkpad_acpi() */
#include "thinkpad_helper.c" #include "thinkpad_helper.c"
...@@ -5549,6 +5557,7 @@ enum { ...@@ -5549,6 +5557,7 @@ enum {
ALC293_FIXUP_LENOVO_SPK_NOISE, ALC293_FIXUP_LENOVO_SPK_NOISE,
ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY, ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY,
ALC255_FIXUP_DELL_SPK_NOISE, ALC255_FIXUP_DELL_SPK_NOISE,
ALC225_FIXUP_DISABLE_MIC_VREF,
ALC225_FIXUP_DELL1_MIC_NO_PRESENCE, ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
ALC295_FIXUP_DISABLE_DAC3, ALC295_FIXUP_DISABLE_DAC3,
ALC280_FIXUP_HP_HEADSET_MIC, ALC280_FIXUP_HP_HEADSET_MIC,
...@@ -6268,6 +6277,12 @@ static const struct hda_fixup alc269_fixups[] = { ...@@ -6268,6 +6277,12 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true, .chained = true,
.chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE .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] = { [ALC225_FIXUP_DELL1_MIC_NO_PRESENCE] = {
.type = HDA_FIXUP_VERBS, .type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) { .v.verbs = (const struct hda_verb[]) {
...@@ -6277,7 +6292,7 @@ static const struct hda_fixup alc269_fixups[] = { ...@@ -6277,7 +6292,7 @@ static const struct hda_fixup alc269_fixups[] = {
{} {}
}, },
.chained = true, .chained = true,
.chain_id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE .chain_id = ALC225_FIXUP_DISABLE_MIC_VREF
}, },
[ALC280_FIXUP_HP_HEADSET_MIC] = { [ALC280_FIXUP_HP_HEADSET_MIC] = {
.type = HDA_FIXUP_FUNC, .type = HDA_FIXUP_FUNC,
...@@ -6584,6 +6599,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { ...@@ -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, 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, 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, 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, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x164b, "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), 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) ...@@ -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, h1 = snd_usb_find_csint_desc(host_iface->extra,
host_iface->extralen, host_iface->extralen,
NULL, UAC_HEADER); NULL, UAC_HEADER);
if (!h1) { if (!h1 || h1->bLength < sizeof(*h1)) {
dev_err(&dev->dev, "cannot find UAC_HEADER\n"); dev_err(&dev->dev, "cannot find UAC_HEADER\n");
return -EINVAL; return -EINVAL;
} }
......
...@@ -753,8 +753,9 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state, ...@@ -753,8 +753,9 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
struct uac_mixer_unit_descriptor *desc) struct uac_mixer_unit_descriptor *desc)
{ {
int mu_channels; int mu_channels;
void *c;
if (desc->bLength < 11) if (desc->bLength < sizeof(*desc))
return -EINVAL; return -EINVAL;
if (!desc->bNrInPins) if (!desc->bNrInPins)
return -EINVAL; return -EINVAL;
...@@ -763,6 +764,8 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state, ...@@ -763,6 +764,8 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
case UAC_VERSION_1: case UAC_VERSION_1:
case UAC_VERSION_2: case UAC_VERSION_2:
default: default:
if (desc->bLength < sizeof(*desc) + desc->bNrInPins + 1)
return 0; /* no bmControls -> skip */
mu_channels = uac_mixer_unit_bNrChannels(desc); mu_channels = uac_mixer_unit_bNrChannels(desc);
break; break;
case UAC_VERSION_3: case UAC_VERSION_3:
...@@ -772,7 +775,11 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state, ...@@ -772,7 +775,11 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
} }
if (!mu_channels) 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; return mu_channels;
} }
...@@ -944,7 +951,7 @@ static int check_input_term(struct mixer_build *state, int id, ...@@ -944,7 +951,7 @@ static int check_input_term(struct mixer_build *state, int id,
struct uac_mixer_unit_descriptor *d = p1; struct uac_mixer_unit_descriptor *d = p1;
err = uac_mixer_unit_get_channels(state, d); err = uac_mixer_unit_get_channels(state, d);
if (err < 0) if (err <= 0)
return err; return err;
term->channels = err; term->channels = err;
...@@ -2068,11 +2075,15 @@ static int parse_audio_input_terminal(struct mixer_build *state, int unitid, ...@@ -2068,11 +2075,15 @@ static int parse_audio_input_terminal(struct mixer_build *state, int unitid,
if (state->mixer->protocol == UAC_VERSION_2) { if (state->mixer->protocol == UAC_VERSION_2) {
struct uac2_input_terminal_descriptor *d_v2 = raw_desc; struct uac2_input_terminal_descriptor *d_v2 = raw_desc;
if (d_v2->bLength < sizeof(*d_v2))
return -EINVAL;
control = UAC2_TE_CONNECTOR; control = UAC2_TE_CONNECTOR;
term_id = d_v2->bTerminalID; term_id = d_v2->bTerminalID;
bmctls = le16_to_cpu(d_v2->bmControls); bmctls = le16_to_cpu(d_v2->bmControls);
} else if (state->mixer->protocol == UAC_VERSION_3) { } else if (state->mixer->protocol == UAC_VERSION_3) {
struct uac3_input_terminal_descriptor *d_v3 = raw_desc; struct uac3_input_terminal_descriptor *d_v3 = raw_desc;
if (d_v3->bLength < sizeof(*d_v3))
return -EINVAL;
control = UAC3_TE_INSERTION; control = UAC3_TE_INSERTION;
term_id = d_v3->bTerminalID; term_id = d_v3->bTerminalID;
bmctls = le32_to_cpu(d_v3->bmControls); bmctls = le32_to_cpu(d_v3->bmControls);
...@@ -2118,7 +2129,7 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, ...@@ -2118,7 +2129,7 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid,
if (err < 0) if (err < 0)
continue; continue;
/* no bmControls field (e.g. Maya44) -> ignore */ /* no bmControls field (e.g. Maya44) -> ignore */
if (desc->bLength <= 10 + input_pins) if (!num_outs)
continue; continue;
err = check_input_term(state, desc->baSourceID[pin], &iterm); err = check_input_term(state, desc->baSourceID[pin], &iterm);
if (err < 0) if (err < 0)
...@@ -2314,7 +2325,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, ...@@ -2314,7 +2325,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
char *name) char *name)
{ {
struct uac_processing_unit_descriptor *desc = raw_desc; struct uac_processing_unit_descriptor *desc = raw_desc;
int num_ins = desc->bNrInPins; int num_ins;
struct usb_mixer_elem_info *cval; struct usb_mixer_elem_info *cval;
struct snd_kcontrol *kctl; struct snd_kcontrol *kctl;
int i, err, nameid, type, len; int i, err, nameid, type, len;
...@@ -2329,7 +2340,13 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, ...@@ -2329,7 +2340,13 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
0, NULL, default_value_info 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)) { 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); usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid);
return -EINVAL; return -EINVAL;
......
...@@ -3326,6 +3326,9 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), ...@@ -3326,6 +3326,9 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
} }
} }
}, },
{
.ifnum = -1
},
} }
} }
}, },
...@@ -3369,6 +3372,9 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), ...@@ -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) ...@@ -768,7 +768,7 @@ static int snd_usb_cm6206_boot_quirk(struct usb_device *dev)
* REG1: PLL binary search enable, soft mute enable. * REG1: PLL binary search enable, soft mute enable.
*/ */
CM6206_REG1_PLLBIN_EN | CM6206_REG1_PLLBIN_EN |
CM6206_REG1_SOFT_MUTE_EN | CM6206_REG1_SOFT_MUTE_EN,
/* /*
* REG2: enable output drivers, * REG2: enable output drivers,
* select front channels to the headphone output, * select front channels to the headphone output,
......
...@@ -596,12 +596,8 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, ...@@ -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); csep = snd_usb_find_desc(alts->extra, alts->extralen, NULL, USB_DT_CS_ENDPOINT);
if (!csep || csep->bLength < 7 || if (!csep || csep->bLength < 7 ||
csep->bDescriptorSubtype != UAC_EP_GENERAL) { csep->bDescriptorSubtype != UAC_EP_GENERAL)
usb_audio_warn(chip, goto error;
"%u:%d : no or invalid class specific endpoint descriptor\n",
iface_no, altsd->bAlternateSetting);
return 0;
}
if (protocol == UAC_VERSION_1) { if (protocol == UAC_VERSION_1) {
attributes = csep->bmAttributes; attributes = csep->bmAttributes;
...@@ -609,6 +605,8 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, ...@@ -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 *csep2 =
(struct uac2_iso_endpoint_descriptor *) csep; (struct uac2_iso_endpoint_descriptor *) csep;
if (csep2->bLength < sizeof(*csep2))
goto error;
attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX; attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX;
/* emulate the endpoint attributes of a v1 device */ /* emulate the endpoint attributes of a v1 device */
...@@ -618,12 +616,20 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, ...@@ -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 *csep3 =
(struct uac3_iso_endpoint_descriptor *) csep; (struct uac3_iso_endpoint_descriptor *) csep;
if (csep3->bLength < sizeof(*csep3))
goto error;
/* emulate the endpoint attributes of a v1 device */ /* emulate the endpoint attributes of a v1 device */
if (le32_to_cpu(csep3->bmControls) & UAC2_CONTROL_PITCH) if (le32_to_cpu(csep3->bmControls) & UAC2_CONTROL_PITCH)
attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL; attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
} }
return attributes; 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 /* 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, ...@@ -631,13 +637,17 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
*/ */
static void * static void *
snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface, 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; 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, while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
ctrl_iface->extralen, ctrl_iface->extralen,
term, UAC_INPUT_TERMINAL))) { term, UAC_INPUT_TERMINAL))) {
if (term->bLength < minlen)
continue;
if (term->bTerminalID == terminal_id) if (term->bTerminalID == terminal_id)
return term; return term;
} }
...@@ -655,7 +665,8 @@ snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface, ...@@ -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, while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
ctrl_iface->extralen, ctrl_iface->extralen,
term, UAC_OUTPUT_TERMINAL))) { term, UAC_OUTPUT_TERMINAL))) {
if (term->bTerminalID == terminal_id) if (term->bLength >= sizeof(*term) &&
term->bTerminalID == terminal_id)
return term; return term;
} }
...@@ -729,7 +740,8 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip, ...@@ -729,7 +740,8 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
format = le16_to_cpu(as->wFormatTag); /* remember the format value */ format = le16_to_cpu(as->wFormatTag); /* remember the format value */
iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
as->bTerminalLink); as->bTerminalLink,
false);
if (iterm) { if (iterm) {
num_channels = iterm->bNrChannels; num_channels = iterm->bNrChannels;
chconfig = le16_to_cpu(iterm->wChannelConfig); chconfig = le16_to_cpu(iterm->wChannelConfig);
...@@ -764,7 +776,8 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip, ...@@ -764,7 +776,8 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
* to extract the clock * to extract the clock
*/ */
input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
as->bTerminalLink); as->bTerminalLink,
true);
if (input_term) { if (input_term) {
clock = input_term->bCSourceID; clock = input_term->bCSourceID;
if (!chconfig && (num_channels == input_term->bNrChannels)) if (!chconfig && (num_channels == input_term->bNrChannels))
...@@ -998,7 +1011,8 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip, ...@@ -998,7 +1011,8 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
* to extract the clock * to extract the clock
*/ */
input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
as->bTerminalLink); as->bTerminalLink,
true);
if (input_term) { if (input_term) {
clock = input_term->bCSourceID; clock = input_term->bCSourceID;
goto found_clock; goto found_clock;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment