ALSA: hda - hdmi: Do not expose eld data when eld is invalid
authorDavid Henningsson <david.henningsson@canonical.com>
Tue, 19 Feb 2013 15:11:23 +0000 (16:11 +0100)
committerTakashi Iwai <tiwai@suse.de>
Tue, 19 Feb 2013 17:28:13 +0000 (18:28 +0100)
Previously, it was possible to read the eld data of the previous
monitor connected. This should not be allowed.

Also refactor the function slightly.

Signed-off-by: David Henningsson <david.henningsson@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/hda/patch_hdmi.c

index 32adaa6c5627d397c5c77b3d9bd60afc0ef108f6..6bcdd667f514d970d210b72700a9c4609c9993df 100644 (file)
@@ -343,14 +343,16 @@ static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol,
                        struct snd_ctl_elem_info *uinfo)
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct hdmi_spec *spec;
+       struct hdmi_spec *spec = codec->spec;
+       struct hdmi_eld *eld;
        int pin_idx;
 
-       spec = codec->spec;
        uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
 
        pin_idx = kcontrol->private_value;
-       uinfo->count = spec->pins[pin_idx].sink_eld.eld_size;
+       eld = &spec->pins[pin_idx].sink_eld;
+
+       uinfo->count = eld->eld_valid ? eld->eld_size : 0;
 
        return 0;
 }
@@ -359,14 +361,23 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
                        struct snd_ctl_elem_value *ucontrol)
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct hdmi_spec *spec;
+       struct hdmi_spec *spec = codec->spec;
+       struct hdmi_eld *eld;
        int pin_idx;
 
-       spec = codec->spec;
        pin_idx = kcontrol->private_value;
+       eld = &spec->pins[pin_idx].sink_eld;
+
+       if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data)) {
+               snd_BUG();
+               return -EINVAL;
+       }
 
-       memcpy(ucontrol->value.bytes.data,
-               spec->pins[pin_idx].sink_eld.eld_buffer, ELD_MAX_SIZE);
+       memset(ucontrol->value.bytes.data, 0,
+              ARRAY_SIZE(ucontrol->value.bytes.data));
+       if (eld->eld_valid)
+               memcpy(ucontrol->value.bytes.data, eld->eld_buffer,
+                      eld->eld_size);
 
        return 0;
 }