ALSA: oss: Use kvzalloc() for local buffer allocations
authorTakashi Iwai <tiwai@suse.de>
Fri, 9 Nov 2018 10:59:45 +0000 (11:59 +0100)
committerTakashi Iwai <tiwai@suse.de>
Fri, 9 Nov 2018 13:12:04 +0000 (14:12 +0100)
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>
sound/core/oss/pcm_oss.c
sound/core/oss/pcm_plugin.c

index f8d4a419f3af957a2dd53ba8cf1673da607ec7e0..467039b342b511c7c4fb95f0d7c316f7715d7c70 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 141c5f3a957501e0901102ce5bd519cbca73892e..31cb2acf8afcc5988d47cdb2332c005c0558d18a 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;
 }