lkml.org 
[lkml]   [2022]   [Mar]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.17 05/39] ALSA: oss: Fix PCM OSS buffer allocation overflow
    Date
    From: Takashi Iwai <tiwai@suse.de>

    commit efb6402c3c4a7c26d97c92d70186424097b6e366 upstream.

    We've got syzbot reports hitting INT_MAX overflow at vmalloc()
    allocation that is called from snd_pcm_plug_alloc(). Although we
    apply the restrictions to input parameters, it's based only on the
    hw_params of the underlying PCM device. Since the PCM OSS layer
    allocates a temporary buffer for the data conversion, the size may
    become unexpectedly large when more channels or higher rates is given;
    in the reported case, it went over INT_MAX, hence it hits WARN_ON().

    This patch is an attempt to avoid such an overflow and an allocation
    for too large buffers. First off, it adds the limit of 1MB as the
    upper bound for period bytes. This must be large enough for all use
    cases, and we really don't want to handle a larger temporary buffer
    than this size. The size check is performed at two places, where the
    original period bytes is calculated and where the plugin buffer size
    is calculated.

    In addition, the driver uses array_size() and array3_size() for
    multiplications to catch overflows for the converted period size and
    buffer bytes.

    Reported-by: syzbot+72732c532ac1454eeee9@syzkaller.appspotmail.com
    Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: <stable@vger.kernel.org>
    Link: https://lore.kernel.org/r/00000000000085b1b305da5a66f3@google.com
    Link: https://lore.kernel.org/r/20220318082036.29699-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_oss.c | 12 ++++++++----
    sound/core/oss/pcm_plugin.c | 5 ++++-
    2 files changed, 12 insertions(+), 5 deletions(-)

    --- a/sound/core/oss/pcm_oss.c
    +++ b/sound/core/oss/pcm_oss.c
    @@ -774,6 +774,11 @@ static int snd_pcm_oss_period_size(struc

    if (oss_period_size < 16)
    return -EINVAL;
    +
    + /* don't allocate too large period; 1MB period must be enough */
    + if (oss_period_size > 1024 * 1024)
    + return -ENOMEM;
    +
    runtime->oss.period_bytes = oss_period_size;
    runtime->oss.period_frames = 1;
    runtime->oss.periods = oss_periods;
    @@ -1043,10 +1048,9 @@ static int snd_pcm_oss_change_params_loc
    goto failure;
    }
    #endif
    - oss_period_size *= oss_frame_size;
    -
    - oss_buffer_size = oss_period_size * runtime->oss.periods;
    - if (oss_buffer_size < 0) {
    + oss_period_size = array_size(oss_period_size, oss_frame_size);
    + oss_buffer_size = array_size(oss_period_size, runtime->oss.periods);
    + if (oss_buffer_size <= 0) {
    err = -EINVAL;
    goto failure;
    }
    --- a/sound/core/oss/pcm_plugin.c
    +++ b/sound/core/oss/pcm_plugin.c
    @@ -62,7 +62,10 @@ static int snd_pcm_plugin_alloc(struct s
    width = snd_pcm_format_physical_width(format->format);
    if (width < 0)
    return width;
    - size = frames * format->channels * width;
    + size = array3_size(frames, format->channels, width);
    + /* check for too large period size once again */
    + if (size > 1024 * 1024)
    + return -ENOMEM;
    if (snd_BUG_ON(size % 8))
    return -ENXIO;
    size /= 8;

    \
     
     \ /
      Last update: 2022-03-25 16:31    [W:3.940 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site