Skip to content

Commit

Permalink
ALSA: mixer: oss: Fix racy access to slots
Browse files Browse the repository at this point in the history
The OSS mixer can reassign the mapping slots dynamically via proc
file.  Although the addition and deletion of those slots are protected
by mixer->reg_mutex, the access to slots aren't, hence this may cause
UAF when the slots in use are deleted concurrently.

This patch applies the mixer->reg_mutex in all appropriate code paths
(i.e. the ioctl functions) that may access slots.

Reported-by: [email protected]
Reviewed-by: Jaroslav Kysela <[email protected]>
Cc: <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Takashi Iwai <[email protected]>
  • Loading branch information
tiwai committed Oct 21, 2021
1 parent 2966492 commit 411cef6
Showing 1 changed file with 33 additions and 11 deletions.
44 changes: 33 additions & 11 deletions sound/core/oss/mixer_oss.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,13 @@ static int snd_mixer_oss_devmask(struct snd_mixer_oss_file *fmixer)

if (mixer == NULL)
return -EIO;
mutex_lock(&mixer->reg_mutex);
for (chn = 0; chn < 31; chn++) {
pslot = &mixer->slots[chn];
if (pslot->put_volume || pslot->put_recsrc)
result |= 1 << chn;
}
mutex_unlock(&mixer->reg_mutex);
return result;
}

Expand All @@ -146,11 +148,13 @@ static int snd_mixer_oss_stereodevs(struct snd_mixer_oss_file *fmixer)

if (mixer == NULL)
return -EIO;
mutex_lock(&mixer->reg_mutex);
for (chn = 0; chn < 31; chn++) {
pslot = &mixer->slots[chn];
if (pslot->put_volume && pslot->stereo)
result |= 1 << chn;
}
mutex_unlock(&mixer->reg_mutex);
return result;
}

Expand All @@ -161,6 +165,7 @@ static int snd_mixer_oss_recmask(struct snd_mixer_oss_file *fmixer)

if (mixer == NULL)
return -EIO;
mutex_lock(&mixer->reg_mutex);
if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */
result = mixer->mask_recsrc;
} else {
Expand All @@ -172,6 +177,7 @@ static int snd_mixer_oss_recmask(struct snd_mixer_oss_file *fmixer)
result |= 1 << chn;
}
}
mutex_unlock(&mixer->reg_mutex);
return result;
}

Expand All @@ -182,12 +188,12 @@ static int snd_mixer_oss_get_recsrc(struct snd_mixer_oss_file *fmixer)

if (mixer == NULL)
return -EIO;
mutex_lock(&mixer->reg_mutex);
if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */
int err;
unsigned int index;
err = mixer->get_recsrc(fmixer, &index);
if (err < 0)
return err;
result = mixer->get_recsrc(fmixer, &index);
if (result < 0)
goto unlock;
result = 1 << index;
} else {
struct snd_mixer_oss_slot *pslot;
Expand All @@ -202,7 +208,10 @@ static int snd_mixer_oss_get_recsrc(struct snd_mixer_oss_file *fmixer)
}
}
}
return mixer->oss_recsrc = result;
mixer->oss_recsrc = result;
unlock:
mutex_unlock(&mixer->reg_mutex);
return result;
}

static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsrc)
Expand All @@ -215,6 +224,7 @@ static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsr

if (mixer == NULL)
return -EIO;
mutex_lock(&mixer->reg_mutex);
if (mixer->get_recsrc && mixer->put_recsrc) { /* exclusive input */
if (recsrc & ~mixer->oss_recsrc)
recsrc &= ~mixer->oss_recsrc;
Expand All @@ -240,6 +250,7 @@ static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsr
}
}
}
mutex_unlock(&mixer->reg_mutex);
return result;
}

Expand All @@ -251,22 +262,29 @@ static int snd_mixer_oss_get_volume(struct snd_mixer_oss_file *fmixer, int slot)

if (mixer == NULL || slot > 30)
return -EIO;
mutex_lock(&mixer->reg_mutex);
pslot = &mixer->slots[slot];
left = pslot->volume[0];
right = pslot->volume[1];
if (pslot->get_volume)
result = pslot->get_volume(fmixer, pslot, &left, &right);
if (!pslot->stereo)
right = left;
if (snd_BUG_ON(left < 0 || left > 100))
return -EIO;
if (snd_BUG_ON(right < 0 || right > 100))
return -EIO;
if (snd_BUG_ON(left < 0 || left > 100)) {
result = -EIO;
goto unlock;
}
if (snd_BUG_ON(right < 0 || right > 100)) {
result = -EIO;
goto unlock;
}
if (result >= 0) {
pslot->volume[0] = left;
pslot->volume[1] = right;
result = (left & 0xff) | ((right & 0xff) << 8);
}
unlock:
mutex_unlock(&mixer->reg_mutex);
return result;
}

Expand All @@ -279,6 +297,7 @@ static int snd_mixer_oss_set_volume(struct snd_mixer_oss_file *fmixer,

if (mixer == NULL || slot > 30)
return -EIO;
mutex_lock(&mixer->reg_mutex);
pslot = &mixer->slots[slot];
if (left > 100)
left = 100;
Expand All @@ -289,10 +308,13 @@ static int snd_mixer_oss_set_volume(struct snd_mixer_oss_file *fmixer,
if (pslot->put_volume)
result = pslot->put_volume(fmixer, pslot, left, right);
if (result < 0)
return result;
goto unlock;
pslot->volume[0] = left;
pslot->volume[1] = right;
return (left & 0xff) | ((right & 0xff) << 8);
result = (left & 0xff) | ((right & 0xff) << 8);
unlock:
mutex_lock(&mixer->reg_mutex);
return result;
}

static int snd_mixer_oss_ioctl1(struct snd_mixer_oss_file *fmixer, unsigned int cmd, unsigned long arg)
Expand Down

0 comments on commit 411cef6

Please sign in to comment.