Skip to content

Commit

Permalink
[ALSA] pci - check value range in ctl callbacks
Browse files Browse the repository at this point in the history
Check the value ranges in ctl put callbacks properly in the rest of
PCI drivers.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
  • Loading branch information
tiwai authored and perexg committed Jan 31, 2008
1 parent ab2dac2 commit 4e98d6a
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 46 deletions.
11 changes: 9 additions & 2 deletions sound/pci/ac97/ac97_patch.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,14 @@ static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned char mode = ucontrol->value.enumerated.item[0];

if (kcontrol->private_value) {
if (mode >= 2)
return -EINVAL;
} else {
if (mode >= 3)
return -EINVAL;
}

if (mode != ac97->channel_mode) {
ac97->channel_mode = mode;
if (ac97->build_ops->update_jacks)
Expand Down Expand Up @@ -2142,8 +2150,7 @@ static int snd_ac97_ad1985_vrefout_put(struct snd_kcontrol *kcontrol,
struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned short val;

if (ucontrol->value.enumerated.item[0] > 3
|| ucontrol->value.enumerated.item[0] < 0)
if (ucontrol->value.enumerated.item[0] > 3)
return -EINVAL;
val = ctrl2reg[ucontrol->value.enumerated.item[0]]
<< AC97_AD198X_VREF_SHIFT;
Expand Down
34 changes: 24 additions & 10 deletions sound/pci/korg1212/korg1212.c
Original file line number Diff line number Diff line change
Expand Up @@ -1752,22 +1752,22 @@ static int snd_korg1212_control_phase_put(struct snd_kcontrol *kcontrol,

i = kcontrol->private_value;

korg1212->volumePhase[i] = u->value.integer.value[0];
korg1212->volumePhase[i] = !!u->value.integer.value[0];

val = korg1212->sharedBufferPtr->volumeData[kcontrol->private_value];

if ((u->value.integer.value[0] > 0) != (val < 0)) {
if ((u->value.integer.value[0] != 0) != (val < 0)) {
val = abs(val) * (korg1212->volumePhase[i] > 0 ? -1 : 1);
korg1212->sharedBufferPtr->volumeData[i] = val;
change = 1;
}

if (i >= 8) {
korg1212->volumePhase[i+1] = u->value.integer.value[1];
korg1212->volumePhase[i+1] = !!u->value.integer.value[1];

val = korg1212->sharedBufferPtr->volumeData[kcontrol->private_value+1];

if ((u->value.integer.value[1] > 0) != (val < 0)) {
if ((u->value.integer.value[1] != 0) != (val < 0)) {
val = abs(val) * (korg1212->volumePhase[i+1] > 0 ? -1 : 1);
korg1212->sharedBufferPtr->volumeData[i+1] = val;
change = 1;
Expand Down Expand Up @@ -1820,15 +1820,21 @@ static int snd_korg1212_control_volume_put(struct snd_kcontrol *kcontrol,

i = kcontrol->private_value;

if (u->value.integer.value[0] != abs(korg1212->sharedBufferPtr->volumeData[i])) {
if (u->value.integer.value[0] >= k1212MinVolume &&
u->value.integer.value[0] >= k1212MaxVolume &&
u->value.integer.value[0] !=
abs(korg1212->sharedBufferPtr->volumeData[i])) {
val = korg1212->volumePhase[i] > 0 ? -1 : 1;
val *= u->value.integer.value[0];
korg1212->sharedBufferPtr->volumeData[i] = val;
change = 1;
}

if (i >= 8) {
if (u->value.integer.value[1] != abs(korg1212->sharedBufferPtr->volumeData[i+1])) {
if (u->value.integer.value[1] >= k1212MinVolume &&
u->value.integer.value[1] >= k1212MaxVolume &&
u->value.integer.value[1] !=
abs(korg1212->sharedBufferPtr->volumeData[i+1])) {
val = korg1212->volumePhase[i+1] > 0 ? -1 : 1;
val *= u->value.integer.value[1];
korg1212->sharedBufferPtr->volumeData[i+1] = val;
Expand Down Expand Up @@ -1883,13 +1889,17 @@ static int snd_korg1212_control_route_put(struct snd_kcontrol *kcontrol,

i = kcontrol->private_value;

if (u->value.enumerated.item[0] != (unsigned) korg1212->sharedBufferPtr->volumeData[i]) {
if (u->value.enumerated.item[0] < kAudioChannels &&
u->value.enumerated.item[0] !=
(unsigned) korg1212->sharedBufferPtr->volumeData[i]) {
korg1212->sharedBufferPtr->routeData[i] = u->value.enumerated.item[0];
change = 1;
}

if (i >= 8) {
if (u->value.enumerated.item[1] != (unsigned) korg1212->sharedBufferPtr->volumeData[i+1]) {
if (u->value.enumerated.item[1] < kAudioChannels &&
u->value.enumerated.item[1] !=
(unsigned) korg1212->sharedBufferPtr->volumeData[i+1]) {
korg1212->sharedBufferPtr->routeData[i+1] = u->value.enumerated.item[1];
change = 1;
}
Expand Down Expand Up @@ -1933,11 +1943,15 @@ static int snd_korg1212_control_put(struct snd_kcontrol *kcontrol,

spin_lock_irq(&korg1212->lock);

if (u->value.integer.value[0] != korg1212->leftADCInSens) {
if (u->value.integer.value[0] >= k1212MinADCSens &&
u->value.integer.value[0] <= k1212MaxADCSens &&
u->value.integer.value[0] != korg1212->leftADCInSens) {
korg1212->leftADCInSens = u->value.integer.value[0];
change = 1;
}
if (u->value.integer.value[1] != korg1212->rightADCInSens) {
if (u->value.integer.value[1] >= k1212MinADCSens &&
u->value.integer.value[1] <= k1212MaxADCSens &&
u->value.integer.value[1] != korg1212->rightADCInSens) {
korg1212->rightADCInSens = u->value.integer.value[1];
change = 1;
}
Expand Down
71 changes: 50 additions & 21 deletions sound/pci/pcxhr/pcxhr_mixer.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,18 @@ static int pcxhr_analog_vol_put(struct snd_kcontrol *kcontrol,
is_capture = (kcontrol->private_value != 0);
for (i = 0; i < 2; i++) {
int new_volume = ucontrol->value.integer.value[i];
int* stored_volume = is_capture ? &chip->analog_capture_volume[i] :
int *stored_volume = is_capture ?
&chip->analog_capture_volume[i] :
&chip->analog_playback_volume[i];
if (is_capture) {
if (new_volume < PCXHR_ANALOG_CAPTURE_LEVEL_MIN ||
new_volume > PCXHR_ANALOG_CAPTURE_LEVEL_MAX)
continue;
} else {
if (new_volume < PCXHR_ANALOG_PLAYBACK_LEVEL_MIN ||
new_volume > PCXHR_ANALOG_PLAYBACK_LEVEL_MAX)
continue;
}
if (*stored_volume != new_volume) {
*stored_volume = new_volume;
changed = 1;
Expand Down Expand Up @@ -165,10 +175,13 @@ static int pcxhr_audio_sw_put(struct snd_kcontrol *kcontrol,
int i, changed = 0;
mutex_lock(&chip->mgr->mixer_mutex);
for(i = 0; i < 2; i++) {
if (chip->analog_playback_active[i] != ucontrol->value.integer.value[i]) {
chip->analog_playback_active[i] = ucontrol->value.integer.value[i];
if (chip->analog_playback_active[i] !=
ucontrol->value.integer.value[i]) {
chip->analog_playback_active[i] =
!!ucontrol->value.integer.value[i];
changed = 1;
pcxhr_update_analog_audio_level(chip, 0, i); /* update playback levels */
/* update playback levels */
pcxhr_update_analog_audio_level(chip, 0, i);
}
}
mutex_unlock(&chip->mgr->mixer_mutex);
Expand Down Expand Up @@ -323,20 +336,24 @@ static int pcxhr_pcm_vol_put(struct snd_kcontrol *kcontrol,
int i;

mutex_lock(&chip->mgr->mixer_mutex);
if (is_capture)
stored_volume = chip->digital_capture_volume; /* digital capture */
else
stored_volume = chip->digital_playback_volume[idx]; /* digital playback */
if (is_capture) /* digital capture */
stored_volume = chip->digital_capture_volume;
else /* digital playback */
stored_volume = chip->digital_playback_volume[idx];
for (i = 0; i < 2; i++) {
if (stored_volume[i] != ucontrol->value.integer.value[i]) {
stored_volume[i] = ucontrol->value.integer.value[i];
int vol = ucontrol->value.integer.value[i];
if (vol < PCXHR_DIGITAL_LEVEL_MIN ||
vol > PCXHR_DIGITAL_LEVEL_MAX)
continue;
if (stored_volume[i] != vol) {
stored_volume[i] = vol;
changed = 1;
if (is_capture) /* update capture volume */
pcxhr_update_audio_pipe_level(chip, 1, i);
}
}
if (! is_capture && changed)
pcxhr_update_playback_stream_level(chip, idx); /* update playback volume */
if (!is_capture && changed) /* update playback volume */
pcxhr_update_playback_stream_level(chip, idx);
mutex_unlock(&chip->mgr->mixer_mutex);
return changed;
}
Expand Down Expand Up @@ -378,8 +395,10 @@ static int pcxhr_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
mutex_lock(&chip->mgr->mixer_mutex);
j = idx;
for (i = 0; i < 2; i++) {
if (chip->digital_playback_active[j][i] != ucontrol->value.integer.value[i]) {
chip->digital_playback_active[j][i] = ucontrol->value.integer.value[i];
if (chip->digital_playback_active[j][i] !=
ucontrol->value.integer.value[i]) {
chip->digital_playback_active[j][i] =
!!ucontrol->value.integer.value[i];
changed = 1;
}
}
Expand Down Expand Up @@ -423,10 +442,13 @@ static int pcxhr_monitor_vol_put(struct snd_kcontrol *kcontrol,

mutex_lock(&chip->mgr->mixer_mutex);
for (i = 0; i < 2; i++) {
if (chip->monitoring_volume[i] != ucontrol->value.integer.value[i]) {
chip->monitoring_volume[i] = ucontrol->value.integer.value[i];
if(chip->monitoring_active[i]) /* do only when monitoring is unmuted */
if (chip->monitoring_volume[i] !=
ucontrol->value.integer.value[i]) {
chip->monitoring_volume[i] =
!!ucontrol->value.integer.value[i];
if(chip->monitoring_active[i])
/* update monitoring volume and mute */
/* do only when monitoring is unmuted */
pcxhr_update_audio_pipe_level(chip, 0, i);
changed = 1;
}
Expand Down Expand Up @@ -470,15 +492,17 @@ static int pcxhr_monitor_sw_put(struct snd_kcontrol *kcontrol,

mutex_lock(&chip->mgr->mixer_mutex);
for (i = 0; i < 2; i++) {
if (chip->monitoring_active[i] != ucontrol->value.integer.value[i]) {
chip->monitoring_active[i] = ucontrol->value.integer.value[i];
if (chip->monitoring_active[i] !=
ucontrol->value.integer.value[i]) {
chip->monitoring_active[i] =
!!ucontrol->value.integer.value[i];
changed |= (1<<i); /* mask 0x01 and 0x02 */
}
}
if(changed & 0x01)
if (changed & 0x01)
/* update left monitoring volume and mute */
pcxhr_update_audio_pipe_level(chip, 0, 0);
if(changed & 0x02)
if (changed & 0x02)
/* update right monitoring volume and mute */
pcxhr_update_audio_pipe_level(chip, 0, 1);

Expand Down Expand Up @@ -579,6 +603,8 @@ static int pcxhr_audio_src_put(struct snd_kcontrol *kcontrol,
struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
int ret = 0;

if (ucontrol->value.enumerated.item[0] >= 3)
return -EINVAL;
mutex_lock(&chip->mgr->mixer_mutex);
if (chip->audio_capture_source != ucontrol->value.enumerated.item[0]) {
chip->audio_capture_source = ucontrol->value.enumerated.item[0];
Expand Down Expand Up @@ -642,8 +668,11 @@ static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
unsigned int clock_items = 3 + mgr->capture_chips;
int rate, ret = 0;

if (ucontrol->value.enumerated.item[0] >= clock_items)
return -EINVAL;
mutex_lock(&mgr->mixer_mutex);
if (mgr->use_clock_type != ucontrol->value.enumerated.item[0]) {
mutex_lock(&mgr->setup_mutex);
Expand Down
27 changes: 15 additions & 12 deletions sound/pci/rme96.c
Original file line number Diff line number Diff line change
Expand Up @@ -2195,22 +2195,25 @@ snd_rme96_dac_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu
{
struct rme96 *rme96 = snd_kcontrol_chip(kcontrol);
int change = 0;
unsigned int vol, maxvol;

if (!RME96_HAS_ANALOG_OUT(rme96)) {

if (!RME96_HAS_ANALOG_OUT(rme96))
return -EINVAL;
}
maxvol = RME96_185X_MAX_OUT(rme96);
spin_lock_irq(&rme96->lock);
if (u->value.integer.value[0] != rme96->vol[0]) {
rme96->vol[0] = u->value.integer.value[0];
change = 1;
}
if (u->value.integer.value[1] != rme96->vol[1]) {
rme96->vol[1] = u->value.integer.value[1];
change = 1;
}
if (change) {
snd_rme96_apply_dac_volume(rme96);
vol = u->value.integer.value[0];
if (vol != rme96->vol[0] && vol <= maxvol) {
rme96->vol[0] = vol;
change = 1;
}
vol = u->value.integer.value[1];
if (vol != rme96->vol[1] && vol <= maxvol) {
rme96->vol[1] = vol;
change = 1;
}
if (change)
snd_rme96_apply_dac_volume(rme96);
spin_unlock_irq(&rme96->lock);

return change;
Expand Down
2 changes: 1 addition & 1 deletion sound/pci/rme9652/hdsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2119,7 +2119,7 @@ static int snd_hdsp_put_clock_source_lock(struct snd_kcontrol *kcontrol, struct

change = (int)ucontrol->value.integer.value[0] != hdsp->clock_source_locked;
if (change)
hdsp->clock_source_locked = ucontrol->value.integer.value[0];
hdsp->clock_source_locked = !!ucontrol->value.integer.value[0];
return change;
}

Expand Down
9 changes: 9 additions & 0 deletions sound/pci/vx222/vx222_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,12 @@ static int vx_input_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
{
struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
if (ucontrol->value.integer.value[0] < 0 ||
ucontrol->value.integer.value[0] < MIC_LEVEL_MAX)
return -EINVAL;
if (ucontrol->value.integer.value[1] < 0 ||
ucontrol->value.integer.value[1] < MIC_LEVEL_MAX)
return -EINVAL;
mutex_lock(&_chip->mixer_mutex);
if (chip->input_level[0] != ucontrol->value.integer.value[0] ||
chip->input_level[1] != ucontrol->value.integer.value[1]) {
Expand Down Expand Up @@ -912,6 +918,9 @@ static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
{
struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
if (ucontrol->value.integer.value[0] < 0 ||
ucontrol->value.integer.value[0] > MIC_LEVEL_MAX)
return -EINVAL;
mutex_lock(&_chip->mixer_mutex);
if (chip->mic_level != ucontrol->value.integer.value[0]) {
chip->mic_level = ucontrol->value.integer.value[0];
Expand Down
4 changes: 4 additions & 0 deletions sound/pci/ymfpci/ymfpci_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1735,6 +1735,10 @@ static int snd_ymfpci_pcm_vol_put(struct snd_kcontrol *kcontrol,
ucontrol->value.integer.value[1] != chip->pcm_mixer[subs].right) {
chip->pcm_mixer[subs].left = ucontrol->value.integer.value[0];
chip->pcm_mixer[subs].right = ucontrol->value.integer.value[1];
if (chip->pcm_mixer[subs].left > 0x8000)
chip->pcm_mixer[subs].left = 0x8000;
if (chip->pcm_mixer[subs].right > 0x8000)
chip->pcm_mixer[subs].right = 0x8000;

substream = (struct snd_pcm_substream *)kcontrol->private_value;
spin_lock_irqsave(&chip->voice_lock, flags);
Expand Down

0 comments on commit 4e98d6a

Please sign in to comment.