| From 4cc8d6505ab82db3357613d36e6c58a297f57f7c Mon Sep 17 00:00:00 2001 |
| From: Takashi Iwai <tiwai@suse.de> |
| Date: Wed, 4 Dec 2019 15:48:24 +0100 |
| Subject: ALSA: pcm: oss: Avoid potential buffer overflows |
| |
| From: Takashi Iwai <tiwai@suse.de> |
| |
| commit 4cc8d6505ab82db3357613d36e6c58a297f57f7c upstream. |
| |
| syzkaller reported an invalid access in PCM OSS read, and this seems |
| to be an overflow of the internal buffer allocated for a plugin. |
| Since the rate plugin adjusts its transfer size dynamically, the |
| calculation for the chained plugin might be bigger than the given |
| buffer size in some extreme cases, which lead to such an buffer |
| overflow as caught by KASAN. |
| |
| Fix it by limiting the max transfer size properly by checking against |
| the destination size in each plugin transfer callback. |
| |
| Reported-by: syzbot+f153bde47a62e0b05f83@syzkaller.appspotmail.com |
| Cc: <stable@vger.kernel.org> |
| Link: https://lore.kernel.org/r/20191204144824.17801-1-tiwai@suse.de |
| Signed-off-by: Takashi Iwai <tiwai@suse.de> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| sound/core/oss/linear.c | 2 ++ |
| sound/core/oss/mulaw.c | 2 ++ |
| sound/core/oss/route.c | 2 ++ |
| 3 files changed, 6 insertions(+) |
| |
| --- a/sound/core/oss/linear.c |
| +++ b/sound/core/oss/linear.c |
| @@ -107,6 +107,8 @@ static snd_pcm_sframes_t linear_transfer |
| } |
| } |
| #endif |
| + if (frames > dst_channels[0].frames) |
| + frames = dst_channels[0].frames; |
| convert(plugin, src_channels, dst_channels, frames); |
| return frames; |
| } |
| --- a/sound/core/oss/mulaw.c |
| +++ b/sound/core/oss/mulaw.c |
| @@ -269,6 +269,8 @@ static snd_pcm_sframes_t mulaw_transfer( |
| } |
| } |
| #endif |
| + if (frames > dst_channels[0].frames) |
| + frames = dst_channels[0].frames; |
| data = (struct mulaw_priv *)plugin->extra_data; |
| data->func(plugin, src_channels, dst_channels, frames); |
| return frames; |
| --- a/sound/core/oss/route.c |
| +++ b/sound/core/oss/route.c |
| @@ -57,6 +57,8 @@ static snd_pcm_sframes_t route_transfer( |
| return -ENXIO; |
| if (frames == 0) |
| return 0; |
| + if (frames > dst_channels[0].frames) |
| + frames = dst_channels[0].frames; |
| |
| nsrcs = plugin->src_format.channels; |
| ndsts = plugin->dst_format.channels; |