summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2019-12-04 15:48:24 +0100
committerTakashi Iwai <tiwai@suse.de>2019-12-04 15:51:30 +0100
commit4cc8d6505ab82db3357613d36e6c58a297f57f7c (patch)
tree47516d45861f38b6a35029f906025922b0723ade
parentALSA: hda: hdmi - Keep old slot assignment behavior for Intel platforms (diff)
downloadlinux-4cc8d6505ab82db3357613d36e6c58a297f57f7c.tar.xz
linux-4cc8d6505ab82db3357613d36e6c58a297f57f7c.zip
ALSA: pcm: oss: Avoid potential buffer overflows
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>
-rw-r--r--sound/core/oss/linear.c2
-rw-r--r--sound/core/oss/mulaw.c2
-rw-r--r--sound/core/oss/route.c2
3 files changed, 6 insertions, 0 deletions
diff --git a/sound/core/oss/linear.c b/sound/core/oss/linear.c
index 2045697f449d..797d838a2f9e 100644
--- a/sound/core/oss/linear.c
+++ b/sound/core/oss/linear.c
@@ -107,6 +107,8 @@ static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin,
}
}
#endif
+ if (frames > dst_channels[0].frames)
+ frames = dst_channels[0].frames;
convert(plugin, src_channels, dst_channels, frames);
return frames;
}
diff --git a/sound/core/oss/mulaw.c b/sound/core/oss/mulaw.c
index 7915564bd394..3788906421a7 100644
--- a/sound/core/oss/mulaw.c
+++ b/sound/core/oss/mulaw.c
@@ -269,6 +269,8 @@ static snd_pcm_sframes_t mulaw_transfer(struct snd_pcm_plugin *plugin,
}
}
#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;
diff --git a/sound/core/oss/route.c b/sound/core/oss/route.c
index c8171f5783c8..72dea04197ef 100644
--- a/sound/core/oss/route.c
+++ b/sound/core/oss/route.c
@@ -57,6 +57,8 @@ static snd_pcm_sframes_t route_transfer(struct snd_pcm_plugin *plugin,
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;