From: Takashi Iwai Date: Sat, 10 Mar 2018 22:04:23 +0000 (+0100) Subject: ALSA: pcm: Fix UAF in snd_pcm_oss_get_formats() X-Git-Tag: v4.1.52~466 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2cd1008f21bd10b1b6cbae3fc51e03e9e4aa9c36;p=thirdparty%2Fkernel%2Fstable.git ALSA: pcm: Fix UAF in snd_pcm_oss_get_formats() [ Upstream commit 01c0b4265cc16bc1f43f475c5944c55c10d5768f ] 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: Signed-off-by: Takashi Iwai Signed-off-by: Sasha Levin --- diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 494b7b5333668..daa1feac66bf7 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -1814,10 +1814,9 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) return -ENOMEM; _snd_pcm_hw_params_any(params); err = snd_pcm_hw_refine(substream, params); - format_mask = *hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - kfree(params); if (err < 0) - return err; + goto error; + format_mask = *hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); for (fmt = 0; fmt < 32; ++fmt) { if (snd_mask_test(&format_mask, fmt)) { int f = snd_pcm_oss_format_to(fmt); @@ -1825,7 +1824,10 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) 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)