浏览代码

ALSA: hda/realtek - Fix overflow of vol/sw check bitmap

The bitmap introduced in the commit [527e4d73: ALSA: hda/realtek - Fix
missing volume controls with ALC260] is too narrow for some codecs,
which may have more NIDs than 0x20, thus it may overflow the bitmap
array on them.

Just double the number to cover all and also add a sanity-check code
to be safer.

Cc: <stable@kernel.org> [v3.2+]
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Takashi Iwai 13 年之前
父节点
当前提交
c14c95f62e
共有 1 个文件被更改,包括 8 次插入3 次删除
  1. 8 3
      sound/pci/hda/patch_realtek.c

+ 8 - 3
sound/pci/hda/patch_realtek.c

@@ -80,6 +80,8 @@ enum {
 	ALC_AUTOMUTE_MIXER,	/* mute/unmute mixer widget AMP */
 	ALC_AUTOMUTE_MIXER,	/* mute/unmute mixer widget AMP */
 };
 };
 
 
+#define MAX_VOL_NIDS	0x40
+
 struct alc_spec {
 struct alc_spec {
 	/* codec parameterization */
 	/* codec parameterization */
 	const struct snd_kcontrol_new *mixers[5];	/* mixer arrays */
 	const struct snd_kcontrol_new *mixers[5];	/* mixer arrays */
@@ -118,8 +120,8 @@ struct alc_spec {
 	const hda_nid_t *capsrc_nids;
 	const hda_nid_t *capsrc_nids;
 	hda_nid_t dig_in_nid;		/* digital-in NID; optional */
 	hda_nid_t dig_in_nid;		/* digital-in NID; optional */
 	hda_nid_t mixer_nid;		/* analog-mixer NID */
 	hda_nid_t mixer_nid;		/* analog-mixer NID */
-	DECLARE_BITMAP(vol_ctls, 0x20 << 1);
-	DECLARE_BITMAP(sw_ctls, 0x20 << 1);
+	DECLARE_BITMAP(vol_ctls, MAX_VOL_NIDS << 1);
+	DECLARE_BITMAP(sw_ctls, MAX_VOL_NIDS << 1);
 
 
 	/* capture setup for dynamic dual-adc switch */
 	/* capture setup for dynamic dual-adc switch */
 	hda_nid_t cur_adc;
 	hda_nid_t cur_adc;
@@ -3149,7 +3151,10 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
 static inline unsigned int get_ctl_pos(unsigned int data)
 static inline unsigned int get_ctl_pos(unsigned int data)
 {
 {
 	hda_nid_t nid = get_amp_nid_(data);
 	hda_nid_t nid = get_amp_nid_(data);
-	unsigned int dir = get_amp_direction_(data);
+	unsigned int dir;
+	if (snd_BUG_ON(nid >= MAX_VOL_NIDS))
+		return 0;
+	dir = get_amp_direction_(data);
 	return (nid << 1) | dir;
 	return (nid << 1) | dir;
 }
 }