[alsa-devel] [ALSA hda_codec 1/1] NULL pointer deference fixes for slave_dig_outs
From: Robin H. Johnson robbat2@gentoo.org
The new multiple digital output code forgot to check the slave_dig_outs for NULL in several places. This manifests as an OOPS when changing volume amongst other things.
Signed-off-by: Robin H. Johnson robbat2@gentoo.org
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 696d77e..b22061b 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1462,14 +1462,15 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, AC_VERB_SET_DIGI_CONVERT_2, val >> 8);
- for (d = codec->slave_dig_outs; *d; d++) { - snd_hda_codec_write_cache(codec, *d, 0, - AC_VERB_SET_DIGI_CONVERT_1, - val & 0xff); - snd_hda_codec_write_cache(codec, *d, 0, - AC_VERB_SET_DIGI_CONVERT_2, - val >> 8); - } + if (codec->slave_dig_outs) + for (d = codec->slave_dig_outs; *d; d++) { + snd_hda_codec_write_cache(codec, *d, 0, + AC_VERB_SET_DIGI_CONVERT_1, + val & 0xff); + snd_hda_codec_write_cache(codec, *d, 0, + AC_VERB_SET_DIGI_CONVERT_2, + val >> 8); + } }
mutex_unlock(&codec->spdif_mutex); @@ -1507,10 +1508,12 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, AC_VERB_SET_DIGI_CONVERT_1, val & 0xff);
- for (d = codec->slave_dig_outs; *d; d++) - snd_hda_codec_write_cache(codec, *d, 0, - AC_VERB_SET_DIGI_CONVERT_1, - val & 0xff); + if (codec->slave_dig_outs) + for (d = codec->slave_dig_outs; *d; d++) + snd_hda_codec_write_cache(codec, *d, 0, + AC_VERB_SET_DIGI_CONVERT_1, + val & 0xff); + /* unmute amp switch (if any) */ if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) && (val & AC_DIG1_ENABLE)) @@ -1664,9 +1667,10 @@ static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol, snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val);
- for (d = codec->slave_dig_outs; *d; d++) - snd_hda_codec_write_cache(codec, *d, 0, - AC_VERB_SET_DIGI_CONVERT_1, val); + if (codec->slave_dig_outs) + for (d = codec->slave_dig_outs; *d; d++) + snd_hda_codec_write_cache(codec, *d, 0, + AC_VERB_SET_DIGI_CONVERT_1, val); } mutex_unlock(&codec->spdif_mutex); return change; @@ -2617,10 +2621,11 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
- for (d = codec->slave_dig_outs; *d; d++) - snd_hda_codec_write(codec, *d, 0, - AC_VERB_SET_DIGI_CONVERT_1, - codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); + if (codec->slave_dig_outs) + for (d = codec->slave_dig_outs; *d; d++) + snd_hda_codec_write(codec, *d, 0, + AC_VERB_SET_DIGI_CONVERT_1, + codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); } snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); /* turn on again (if needed) */ @@ -2628,10 +2633,11 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, codec->spdif_ctls & 0xff);
- for (d = codec->slave_dig_outs; *d; d++) - snd_hda_codec_write(codec, *d, 0, - AC_VERB_SET_DIGI_CONVERT_1, - codec->spdif_ctls & 0xff); + if (codec->slave_dig_outs) + for (d = codec->slave_dig_outs; *d; d++) + snd_hda_codec_write(codec, *d, 0, + AC_VERB_SET_DIGI_CONVERT_1, + codec->spdif_ctls & 0xff); }
}
At Sat, 13 Sep 2008 04:18:46 -0700, robbat2@gentoo.org wrote:
From: Robin H. Johnson robbat2@gentoo.org
The new multiple digital output code forgot to check the slave_dig_outs for NULL in several places. This manifests as an OOPS when changing volume amongst other things.
Signed-off-by: Robin H. Johnson robbat2@gentoo.org
I already applied a patch from Herton that fixes the very same issue.
Thanks anyway!
Takashi
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 696d77e..b22061b 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1462,14 +1462,15 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, AC_VERB_SET_DIGI_CONVERT_2, val >> 8);
for (d = codec->slave_dig_outs; *d; d++) {
snd_hda_codec_write_cache(codec, *d, 0,
AC_VERB_SET_DIGI_CONVERT_1,
val & 0xff);
snd_hda_codec_write_cache(codec, *d, 0,
AC_VERB_SET_DIGI_CONVERT_2,
val >> 8);
}
if (codec->slave_dig_outs)
for (d = codec->slave_dig_outs; *d; d++) {
snd_hda_codec_write_cache(codec, *d, 0,
AC_VERB_SET_DIGI_CONVERT_1,
val & 0xff);
snd_hda_codec_write_cache(codec, *d, 0,
AC_VERB_SET_DIGI_CONVERT_2,
val >> 8);
}
}
mutex_unlock(&codec->spdif_mutex);
@@ -1507,10 +1508,12 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, AC_VERB_SET_DIGI_CONVERT_1, val & 0xff);
for (d = codec->slave_dig_outs; *d; d++)
snd_hda_codec_write_cache(codec, *d, 0,
AC_VERB_SET_DIGI_CONVERT_1,
val & 0xff);
if (codec->slave_dig_outs)
for (d = codec->slave_dig_outs; *d; d++)
snd_hda_codec_write_cache(codec, *d, 0,
AC_VERB_SET_DIGI_CONVERT_1,
val & 0xff);
- /* unmute amp switch (if any) */ if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) && (val & AC_DIG1_ENABLE))
@@ -1664,9 +1667,10 @@ static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol, snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val);
for (d = codec->slave_dig_outs; *d; d++)
snd_hda_codec_write_cache(codec, *d, 0,
AC_VERB_SET_DIGI_CONVERT_1, val);
if (codec->slave_dig_outs)
for (d = codec->slave_dig_outs; *d; d++)
snd_hda_codec_write_cache(codec, *d, 0,
} mutex_unlock(&codec->spdif_mutex); return change;AC_VERB_SET_DIGI_CONVERT_1, val);
@@ -2617,10 +2621,11 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
for (d = codec->slave_dig_outs; *d; d++)
snd_hda_codec_write(codec, *d, 0,
AC_VERB_SET_DIGI_CONVERT_1,
codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
if (codec->slave_dig_outs)
for (d = codec->slave_dig_outs; *d; d++)
snd_hda_codec_write(codec, *d, 0,
AC_VERB_SET_DIGI_CONVERT_1,
} snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); /* turn on again (if needed) */codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
@@ -2628,10 +2633,11 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, codec->spdif_ctls & 0xff);
for (d = codec->slave_dig_outs; *d; d++)
snd_hda_codec_write(codec, *d, 0,
AC_VERB_SET_DIGI_CONVERT_1,
codec->spdif_ctls & 0xff);
if (codec->slave_dig_outs)
for (d = codec->slave_dig_outs; *d; d++)
snd_hda_codec_write(codec, *d, 0,
AC_VERB_SET_DIGI_CONVERT_1,
}codec->spdif_ctls & 0xff);
}
1.6.0.1
participants (2)
-
robbat2@gentoo.org
-
Takashi Iwai