ALSA: oss: Use kvzalloc() for local buffer allocations
authorTakashi Iwai <tiwai@suse.de>
Fri, 9 Nov 2018 10:59:45 +0000 (11:59 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 1 Dec 2018 08:42:49 +0000 (09:42 +0100)
commit 65766ee0bf7fe8b3be80e2e1c3ef54ad59b29476 upstream.

PCM OSS layer may allocate a few temporary buffers, one for the core
read/write and another for the conversions via plugins.  Currently
both are allocated via vmalloc().  But as the allocation size is
equivalent with the PCM period size, the required size might be quite
small, depending on the application.

This patch replaces these vmalloc() calls with kvzalloc() for covering
small period sizes better.  Also, we use "z"-alloc variant here for
addressing the possible uninitialized access reported by syzkaller.

Reported-by: syzbot+1cb36954e127c98dd037@syzkaller.appspotmail.com
Cc: <stable@vger.kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
sound/core/oss/pcm_oss.c
sound/core/oss/pcm_plugin.c

index b4f954e6d2db71d245b6b6bac6252800c889d5ff..df358e838b5bd81d0364724918e978c2d4920443 100644 (file)
@@ -1062,8 +1062,8 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
        runtime->oss.channels = params_channels(params);
        runtime->oss.rate = params_rate(params);
 
-       vfree(runtime->oss.buffer);
-       runtime->oss.buffer = vmalloc(runtime->oss.period_bytes);
+       kvfree(runtime->oss.buffer);
+       runtime->oss.buffer = kvzalloc(runtime->oss.period_bytes, GFP_KERNEL);
        if (!runtime->oss.buffer) {
                err = -ENOMEM;
                goto failure;
@@ -2328,7 +2328,7 @@ static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime;
        runtime = substream->runtime;
-       vfree(runtime->oss.buffer);
+       kvfree(runtime->oss.buffer);
        runtime->oss.buffer = NULL;
 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
        snd_pcm_oss_plugin_clear(substream);
index 85a56af104bd619160ace33f51ad2786eca3279a..617845d4a811b2b26a5367353725319e18e17124 100644 (file)
@@ -66,8 +66,8 @@ static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t
                return -ENXIO;
        size /= 8;
        if (plugin->buf_frames < frames) {
-               vfree(plugin->buf);
-               plugin->buf = vmalloc(size);
+               kvfree(plugin->buf);
+               plugin->buf = kvzalloc(size, GFP_KERNEL);
                plugin->buf_frames = frames;
        }
        if (!plugin->buf) {
@@ -191,7 +191,7 @@ int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin)
        if (plugin->private_free)
                plugin->private_free(plugin);
        kfree(plugin->buf_channels);
-       vfree(plugin->buf);
+       kvfree(plugin->buf);
        kfree(plugin);
        return 0;
 }