lkml.org 
[lkml]   [2020]   [Apr]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.9 016/102] ALSA: pcm: oss: Avoid plugin buffer overflow
    Date
    From: Takashi Iwai <tiwai@suse.de>

    commit f2ecf903ef06eb1bbbfa969db9889643d487e73a upstream.

    Each OSS PCM plugins allocate its internal buffer per pre-calculation
    of the max buffer size through the chain of plugins (calling
    src_frames and dst_frames callbacks). This works for most plugins,
    but the rate plugin might behave incorrectly. The calculation in the
    rate plugin involves with the fractional position, i.e. it may vary
    depending on the input position. Since the buffer size
    pre-calculation is always done with the offset zero, it may return a
    shorter size than it might be; this may result in the out-of-bound
    access as spotted by fuzzer.

    This patch addresses those possible buffer overflow accesses by simply
    setting the upper limit per the given buffer size for each plugin
    before src_frames() and after dst_frames() calls.

    Reported-by: syzbot+e1fe9f44fb8ecf4fb5dd@syzkaller.appspotmail.com
    Cc: <stable@vger.kernel.org>
    Link: https://lore.kernel.org/r/000000000000b25ea005a02bcf21@google.com
    Link: https://lore.kernel.org/r/20200309082148.19855-1-tiwai@suse.de
    Signed-off-by: Takashi Iwai <tiwai@suse.de>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    sound/core/oss/pcm_plugin.c | 8 ++++++++
    1 file changed, 8 insertions(+)

    --- a/sound/core/oss/pcm_plugin.c
    +++ b/sound/core/oss/pcm_plugin.c
    @@ -209,6 +209,8 @@ snd_pcm_sframes_t snd_pcm_plug_client_si
    if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
    plugin = snd_pcm_plug_last(plug);
    while (plugin && drv_frames > 0) {
    + if (drv_frames > plugin->buf_frames)
    + drv_frames = plugin->buf_frames;
    plugin_prev = plugin->prev;
    if (plugin->src_frames)
    drv_frames = plugin->src_frames(plugin, drv_frames);
    @@ -220,6 +222,8 @@ snd_pcm_sframes_t snd_pcm_plug_client_si
    plugin_next = plugin->next;
    if (plugin->dst_frames)
    drv_frames = plugin->dst_frames(plugin, drv_frames);
    + if (drv_frames > plugin->buf_frames)
    + drv_frames = plugin->buf_frames;
    plugin = plugin_next;
    }
    } else
    @@ -248,11 +252,15 @@ snd_pcm_sframes_t snd_pcm_plug_slave_siz
    if (frames < 0)
    return frames;
    }
    + if (frames > plugin->buf_frames)
    + frames = plugin->buf_frames;
    plugin = plugin_next;
    }
    } else if (stream == SNDRV_PCM_STREAM_CAPTURE) {
    plugin = snd_pcm_plug_last(plug);
    while (plugin) {
    + if (frames > plugin->buf_frames)
    + frames = plugin->buf_frames;
    plugin_prev = plugin->prev;
    if (plugin->src_frames) {
    frames = plugin->src_frames(plugin, frames);

    \
     
     \ /
      Last update: 2020-04-01 18:53    [W:3.828 / U:0.024 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site