Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c6bebccd authored by Takashi Iwai's avatar Takashi Iwai Committed by Greg Kroah-Hartman
Browse files

ALSA: pcm: oss: Avoid potential buffer overflows



commit 4cc8d6505ab82db3357613d36e6c58a297f57f7c upstream.

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: default avatar <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: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f9f56eb9
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -107,6 +107,8 @@ static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin,
		}
		}
	}
	}
#endif
#endif
	if (frames > dst_channels[0].frames)
		frames = dst_channels[0].frames;
	convert(plugin, src_channels, dst_channels, frames);
	convert(plugin, src_channels, dst_channels, frames);
	return frames;
	return frames;
}
}
+2 −0
Original line number Original line Diff line number Diff line
@@ -269,6 +269,8 @@ static snd_pcm_sframes_t mulaw_transfer(struct snd_pcm_plugin *plugin,
		}
		}
	}
	}
#endif
#endif
	if (frames > dst_channels[0].frames)
		frames = dst_channels[0].frames;
	data = (struct mulaw_priv *)plugin->extra_data;
	data = (struct mulaw_priv *)plugin->extra_data;
	data->func(plugin, src_channels, dst_channels, frames);
	data->func(plugin, src_channels, dst_channels, frames);
	return frames;
	return frames;
+2 −0
Original line number Original line Diff line number Diff line
@@ -57,6 +57,8 @@ static snd_pcm_sframes_t route_transfer(struct snd_pcm_plugin *plugin,
		return -ENXIO;
		return -ENXIO;
	if (frames == 0)
	if (frames == 0)
		return 0;
		return 0;
	if (frames > dst_channels[0].frames)
		frames = dst_channels[0].frames;


	nsrcs = plugin->src_format.channels;
	nsrcs = plugin->src_format.channels;
	ndsts = plugin->dst_format.channels;
	ndsts = plugin->dst_format.channels;