From 74415a36767d99d3adf31b4a62e4e50725e6b66a Mon Sep 17 00:00:00 2001 From: James Courtier-Dutton Date: Mon, 12 Nov 2007 14:55:19 +0000 Subject: [ALSA] emu10k1: Add mixer controls parameter checking. Signed-off-by: James Courtier-Dutton Signed-off-by: Jaroslav Kysela --- sound/pci/emu10k1/emumixer.c | 60 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 9 deletions(-) (limited to 'sound/pci/emu10k1/emumixer.c') diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c index 54a2034d8edd..88eab4a461bd 100644 --- a/sound/pci/emu10k1/emumixer.c +++ b/sound/pci/emu10k1/emumixer.c @@ -58,6 +58,9 @@ static int snd_emu10k1_spdif_get(struct snd_kcontrol *kcontrol, unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); unsigned long flags; + /* Limit: emu->spdif_bits */ + if (idx >= 3) + return -EINVAL; spin_lock_irqsave(&emu->reg_lock, flags); ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff; ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff; @@ -272,9 +275,12 @@ static int snd_emu1010_output_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int channel; + unsigned int channel; channel = (kcontrol->private_value) & 0xff; + /* Limit: emu1010_output_dst, emu->emu1010.output_source */ + if (channel >= 24) + return -EINVAL; ucontrol->value.enumerated.item[0] = emu->emu1010.output_source[channel]; return 0; } @@ -285,9 +291,12 @@ static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol, struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); int change = 0; unsigned int val; - int channel; + unsigned int channel; channel = (kcontrol->private_value) & 0xff; + /* Limit: emu1010_output_dst, emu->emu1010.output_source */ + if (channel >= 24) + return -EINVAL; if (emu->emu1010.output_source[channel] != ucontrol->value.enumerated.item[0]) { val = emu->emu1010.output_source[channel] = ucontrol->value.enumerated.item[0]; change = 1; @@ -301,9 +310,12 @@ static int snd_emu1010_input_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int channel; + unsigned int channel; channel = (kcontrol->private_value) & 0xff; + /* Limit: emu1010_input_dst, emu->emu1010.input_source */ + if (channel >= 22) + return -EINVAL; ucontrol->value.enumerated.item[0] = emu->emu1010.input_source[channel]; return 0; } @@ -314,9 +326,12 @@ static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol, struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); int change = 0; unsigned int val; - int channel; + unsigned int channel; channel = (kcontrol->private_value) & 0xff; + /* Limit: emu1010_input_dst, emu->emu1010.input_source */ + if (channel >= 22) + return -EINVAL; if (emu->emu1010.input_source[channel] != ucontrol->value.enumerated.item[0]) { val = emu->emu1010.input_source[channel] = ucontrol->value.enumerated.item[0]; change = 1; @@ -533,6 +548,9 @@ static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol, int change = 0; val = ucontrol->value.enumerated.item[0] ; + /* Limit: uinfo->value.enumerated.items = 4; */ + if (val >= 4) + return -EINVAL; change = (emu->emu1010.internal_clock != val); if (change) { emu->emu1010.internal_clock = val; @@ -669,7 +687,11 @@ static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol, * update the capture volume from the cached value * for the particular source. */ - source_id = ucontrol->value.enumerated.item[0]; /* Use 2 and 3 */ + source_id = ucontrol->value.enumerated.item[0]; + /* Limit: uinfo->value.enumerated.items = 2; */ + /* emu->i2c_capture_volume */ + if (source_id >= 2) + return -EINVAL; change = (emu->i2c_capture_source != source_id); if (change) { snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */ @@ -720,9 +742,13 @@ static int snd_audigy_i2c_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int source_id; + unsigned int source_id; source_id = kcontrol->private_value; + /* Limit: emu->i2c_capture_volume */ + /* capture_source: uinfo->value.enumerated.items = 2 */ + if (source_id >= 2) + return -EINVAL; ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0]; ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1]; @@ -735,10 +761,14 @@ static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol, struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); unsigned int ogain; unsigned int ngain; - int source_id; + unsigned int source_id; int change = 0; source_id = kcontrol->private_value; + /* Limit: emu->i2c_capture_volume */ + /* capture_source: uinfo->value.enumerated.items = 2 */ + if (source_id >= 2) + return -EINVAL; ogain = emu->i2c_capture_volume[source_id][0]; /* Left */ ngain = ucontrol->value.integer.value[0]; if (ngain > 0xff) @@ -746,7 +776,7 @@ static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol, if (ogain != ngain) { if (emu->i2c_capture_source == source_id) snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) ); - emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0]; + emu->i2c_capture_volume[source_id][0] = ngain; change = 1; } ogain = emu->i2c_capture_volume[source_id][1]; /* Right */ @@ -756,7 +786,7 @@ static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol, if (ogain != ngain) { if (emu->i2c_capture_source == source_id) snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); - emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1]; + emu->i2c_capture_volume[source_id][1] = ngain; change = 1; } @@ -877,6 +907,9 @@ static int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol, unsigned int val; unsigned long flags; + /* Limit: emu->spdif_bits */ + if (idx >= 3) + return -EINVAL; val = (ucontrol->value.iec958.status[0] << 0) | (ucontrol->value.iec958.status[1] << 8) | (ucontrol->value.iec958.status[2] << 16) | @@ -1050,6 +1083,7 @@ static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol, { unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); + /* FIXME: Check limits */ struct snd_emu10k1_pcm_mixer *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; int change = 0, idx, val; @@ -1102,6 +1136,7 @@ static int snd_emu10k1_attn_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); + /* FIXME: Check limits */ struct snd_emu10k1_pcm_mixer *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; unsigned long flags; @@ -1119,6 +1154,7 @@ static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol, { unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); + /* FIXME: Check limits */ struct snd_emu10k1_pcm_mixer *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; int change = 0, idx, val; @@ -1171,6 +1207,7 @@ static int snd_emu10k1_efx_send_routing_get(struct snd_kcontrol *kcontrol, { unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); + /* FIXME: Check limits */ struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; int idx; @@ -1190,6 +1227,7 @@ static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol, { unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); + /* FIXME: Check limits */ int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch]; int change = 0, idx, val; @@ -1241,6 +1279,7 @@ static int snd_emu10k1_efx_send_volume_get(struct snd_kcontrol *kcontrol, { unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); + /* FIXME: Check limits */ struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; int idx; @@ -1258,6 +1297,7 @@ static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol, { unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); + /* FIXME: Check limits */ int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch]; int change = 0, idx, val; @@ -1306,6 +1346,7 @@ static int snd_emu10k1_efx_attn_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); + /* FIXME: Check limits */ struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; unsigned long flags; @@ -1321,6 +1362,7 @@ static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol, { unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); + /* FIXME: Check limits */ int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch]; int change = 0, val; -- cgit v1.2.3 From aa299d01f1c2e680e40813b63f8dfb46c79ea715 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 15 Nov 2007 13:16:02 +0100 Subject: [ALSA] emu10k1 - Check value ranges in ctl callbacks Check value ranges in ctl callbacks properly. This fixes the unexpected crash due to wrong value assignment. Also, remove invalid comments in the last patch. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/emu10k1/emumixer.c | 23 ++++++++++------------- sound/pci/emu10k1/p16v.c | 4 ++++ 2 files changed, 14 insertions(+), 13 deletions(-) (limited to 'sound/pci/emu10k1/emumixer.c') diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c index 88eab4a461bd..ccacd7b890e8 100644 --- a/sound/pci/emu10k1/emumixer.c +++ b/sound/pci/emu10k1/emumixer.c @@ -293,12 +293,15 @@ static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol, unsigned int val; unsigned int channel; + val = ucontrol->value.enumerated.item[0]; + if (val >= 53) + return -EINVAL; channel = (kcontrol->private_value) & 0xff; /* Limit: emu1010_output_dst, emu->emu1010.output_source */ if (channel >= 24) return -EINVAL; - if (emu->emu1010.output_source[channel] != ucontrol->value.enumerated.item[0]) { - val = emu->emu1010.output_source[channel] = ucontrol->value.enumerated.item[0]; + if (emu->emu1010.output_source[channel] != val) { + emu->emu1010.output_source[channel] = val; change = 1; snd_emu1010_fpga_link_dst_src_write(emu, emu1010_output_dst[channel], emu1010_src_regs[val]); @@ -328,12 +331,15 @@ static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol, unsigned int val; unsigned int channel; + val = ucontrol->value.enumerated.item[0]; + if (val >= 53) + return -EINVAL; channel = (kcontrol->private_value) & 0xff; /* Limit: emu1010_input_dst, emu->emu1010.input_source */ if (channel >= 22) return -EINVAL; - if (emu->emu1010.input_source[channel] != ucontrol->value.enumerated.item[0]) { - val = emu->emu1010.input_source[channel] = ucontrol->value.enumerated.item[0]; + if (emu->emu1010.input_source[channel] != val) { + emu->emu1010.input_source[channel] = val; change = 1; snd_emu1010_fpga_link_dst_src_write(emu, emu1010_input_dst[channel], emu1010_src_regs[val]); @@ -1083,7 +1089,6 @@ static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol, { unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - /* FIXME: Check limits */ struct snd_emu10k1_pcm_mixer *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; int change = 0, idx, val; @@ -1136,7 +1141,6 @@ static int snd_emu10k1_attn_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - /* FIXME: Check limits */ struct snd_emu10k1_pcm_mixer *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; unsigned long flags; @@ -1154,7 +1158,6 @@ static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol, { unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - /* FIXME: Check limits */ struct snd_emu10k1_pcm_mixer *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; int change = 0, idx, val; @@ -1207,7 +1210,6 @@ static int snd_emu10k1_efx_send_routing_get(struct snd_kcontrol *kcontrol, { unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - /* FIXME: Check limits */ struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; int idx; @@ -1227,7 +1229,6 @@ static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol, { unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - /* FIXME: Check limits */ int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch]; int change = 0, idx, val; @@ -1279,7 +1280,6 @@ static int snd_emu10k1_efx_send_volume_get(struct snd_kcontrol *kcontrol, { unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - /* FIXME: Check limits */ struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; int idx; @@ -1297,7 +1297,6 @@ static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol, { unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - /* FIXME: Check limits */ int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch]; int change = 0, idx, val; @@ -1346,7 +1345,6 @@ static int snd_emu10k1_efx_attn_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - /* FIXME: Check limits */ struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; unsigned long flags; @@ -1362,7 +1360,6 @@ static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol, { unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - /* FIXME: Check limits */ int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch]; int change = 0, val; diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index d619a3842cdd..9fd3135f3118 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c @@ -742,6 +742,8 @@ static int snd_p16v_capture_source_put(struct snd_kcontrol *kcontrol, u32 source; val = ucontrol->value.enumerated.item[0] ; + if (val > 7) + return -EINVAL; change = (emu->p16v_capture_source != val); if (change) { emu->p16v_capture_source = val; @@ -784,6 +786,8 @@ static int snd_p16v_capture_channel_put(struct snd_kcontrol *kcontrol, u32 tmp; val = ucontrol->value.enumerated.item[0] ; + if (val > 3) + return -EINVAL; change = (emu->p16v_capture_channel != val); if (change) { emu->p16v_capture_channel = val; -- cgit v1.2.3