diff options
Diffstat (limited to 'sound/core/vmaster.c')
-rw-r--r-- | sound/core/vmaster.c | 27 |
1 files changed, 14 insertions, 13 deletions
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c index 378d2c7c3d4a..c657659b236c 100644 --- a/sound/core/vmaster.c +++ b/sound/core/vmaster.c @@ -56,7 +56,7 @@ struct link_follower { static int follower_update(struct link_follower *follower) { - struct snd_ctl_elem_value *uctl; + struct snd_ctl_elem_value *uctl __free(kfree) = NULL; int err, ch; uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); @@ -65,18 +65,16 @@ static int follower_update(struct link_follower *follower) uctl->id = follower->follower.id; err = follower->follower.get(&follower->follower, uctl); if (err < 0) - goto error; + return err; for (ch = 0; ch < follower->info.count; ch++) follower->vals[ch] = uctl->value.integer.value[ch]; - error: - kfree(uctl); - return err < 0 ? err : 0; + return 0; } /* get the follower ctl info and save the initial values */ static int follower_init(struct link_follower *follower) { - struct snd_ctl_elem_info *uinfo; + struct snd_ctl_elem_info *uinfo __free(kfree) = NULL; int err; if (follower->info.count) { @@ -91,22 +89,18 @@ static int follower_init(struct link_follower *follower) return -ENOMEM; uinfo->id = follower->follower.id; err = follower->follower.info(&follower->follower, uinfo); - if (err < 0) { - kfree(uinfo); + if (err < 0) return err; - } follower->info.type = uinfo->type; follower->info.count = uinfo->count; if (follower->info.count > 2 || (follower->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER && follower->info.type != SNDRV_CTL_ELEM_TYPE_BOOLEAN)) { pr_err("ALSA: vmaster: invalid follower element\n"); - kfree(uinfo); return -EINVAL; } follower->info.min_val = uinfo->value.integer.min; follower->info.max_val = uinfo->value.integer.max; - kfree(uinfo); return follower_update(follower); } @@ -205,6 +199,12 @@ static int follower_put(struct snd_kcontrol *kcontrol, if (err < 0) return err; for (ch = 0; ch < follower->info.count; ch++) { + if (ucontrol->value.integer.value[ch] < follower->info.min_val || + ucontrol->value.integer.value[ch] > follower->info.max_val) + return -EINVAL; + } + + for (ch = 0; ch < follower->info.count; ch++) { if (follower->vals[ch] != ucontrol->value.integer.value[ch]) { changed = 1; follower->vals[ch] = ucontrol->value.integer.value[ch]; @@ -341,7 +341,7 @@ static int master_get(struct snd_kcontrol *kcontrol, static int sync_followers(struct link_master *master, int old_val, int new_val) { struct link_follower *follower; - struct snd_ctl_elem_value *uval; + struct snd_ctl_elem_value *uval __free(kfree) = NULL; uval = kmalloc(sizeof(*uval), GFP_KERNEL); if (!uval) @@ -353,7 +353,6 @@ static int sync_followers(struct link_master *master, int old_val, int new_val) master->val = new_val; follower_put_val(follower, uval); } - kfree(uval); return 0; } @@ -372,6 +371,8 @@ static int master_put(struct snd_kcontrol *kcontrol, new_val = ucontrol->value.integer.value[0]; if (new_val == old_val) return 0; + if (new_val < master->info.min_val || new_val > master->info.max_val) + return -EINVAL; err = sync_followers(master, old_val, new_val); if (err < 0) |