ALSA: pcm: Fix UAF in snd_pcm_oss_get_formats()

snd_pcm_oss_get_formats() has an obvious use-after-free around
snd_mask_test() calls, as spotted by syzbot.  The passed format_mask
argument is a pointer to the hw_params object that is freed before the
loop.  What a surprise that it has been present since the original
code of decades ago...

Reported-by: syzbot+4090700a4f13fccaf648@syzkaller.appspotmail.com
Cc: <stable@vger.kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2018-03-10 23:04:23 +01:00
parent a2ff19f7b7
commit 01c0b4265c

View File

@ -1762,10 +1762,9 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
return -ENOMEM; return -ENOMEM;
_snd_pcm_hw_params_any(params); _snd_pcm_hw_params_any(params);
err = snd_pcm_hw_refine(substream, params); err = snd_pcm_hw_refine(substream, params);
format_mask = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
kfree(params);
if (err < 0) if (err < 0)
return err; goto error;
format_mask = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
for (fmt = 0; fmt < 32; ++fmt) { for (fmt = 0; fmt < 32; ++fmt) {
if (snd_mask_test(format_mask, fmt)) { if (snd_mask_test(format_mask, fmt)) {
int f = snd_pcm_oss_format_to(fmt); int f = snd_pcm_oss_format_to(fmt);
@ -1773,7 +1772,10 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
formats |= f; formats |= f;
} }
} }
return formats;
error:
kfree(params);
return err < 0 ? err : formats;
} }
static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int format) static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int format)