Skip to content

Commit ae769d3

Browse files
committed
ALSA: pcm: oss: Fix regression by buffer overflow fix
The recent fix for the OOB access in PCM OSS plugins (commit f2ecf90: "ALSA: pcm: oss: Avoid plugin buffer overflow") caused a regression on OSS applications. The patch introduced the size check in client and slave size calculations to limit to each plugin's buffer size, but I overlooked that some code paths call those without allocating the buffer but just for estimation. This patch fixes the bug by skipping the size check for those code paths while keeping checking in the actual transfer calls. Fixes: f2ecf90 ("ALSA: pcm: oss: Avoid plugin buffer overflow") Tested-and-reported-by: Jari Ruusu <[email protected]> Cc: <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent 5461e05 commit ae769d3

File tree

1 file changed

+24
-8
lines changed

1 file changed

+24
-8
lines changed

sound/core/oss/pcm_plugin.c

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,9 @@ int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin)
196196
return 0;
197197
}
198198

199-
snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug, snd_pcm_uframes_t drv_frames)
199+
static snd_pcm_sframes_t plug_client_size(struct snd_pcm_substream *plug,
200+
snd_pcm_uframes_t drv_frames,
201+
bool check_size)
200202
{
201203
struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next;
202204
int stream;
@@ -209,7 +211,7 @@ snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug, snd_p
209211
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
210212
plugin = snd_pcm_plug_last(plug);
211213
while (plugin && drv_frames > 0) {
212-
if (drv_frames > plugin->buf_frames)
214+
if (check_size && drv_frames > plugin->buf_frames)
213215
drv_frames = plugin->buf_frames;
214216
plugin_prev = plugin->prev;
215217
if (plugin->src_frames)
@@ -222,7 +224,7 @@ snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug, snd_p
222224
plugin_next = plugin->next;
223225
if (plugin->dst_frames)
224226
drv_frames = plugin->dst_frames(plugin, drv_frames);
225-
if (drv_frames > plugin->buf_frames)
227+
if (check_size && drv_frames > plugin->buf_frames)
226228
drv_frames = plugin->buf_frames;
227229
plugin = plugin_next;
228230
}
@@ -231,7 +233,9 @@ snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug, snd_p
231233
return drv_frames;
232234
}
233235

234-
snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pcm_uframes_t clt_frames)
236+
static snd_pcm_sframes_t plug_slave_size(struct snd_pcm_substream *plug,
237+
snd_pcm_uframes_t clt_frames,
238+
bool check_size)
235239
{
236240
struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next;
237241
snd_pcm_sframes_t frames;
@@ -252,14 +256,14 @@ snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pc
252256
if (frames < 0)
253257
return frames;
254258
}
255-
if (frames > plugin->buf_frames)
259+
if (check_size && frames > plugin->buf_frames)
256260
frames = plugin->buf_frames;
257261
plugin = plugin_next;
258262
}
259263
} else if (stream == SNDRV_PCM_STREAM_CAPTURE) {
260264
plugin = snd_pcm_plug_last(plug);
261265
while (plugin) {
262-
if (frames > plugin->buf_frames)
266+
if (check_size && frames > plugin->buf_frames)
263267
frames = plugin->buf_frames;
264268
plugin_prev = plugin->prev;
265269
if (plugin->src_frames) {
@@ -274,6 +278,18 @@ snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pc
274278
return frames;
275279
}
276280

281+
snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug,
282+
snd_pcm_uframes_t drv_frames)
283+
{
284+
return plug_client_size(plug, drv_frames, false);
285+
}
286+
287+
snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug,
288+
snd_pcm_uframes_t clt_frames)
289+
{
290+
return plug_slave_size(plug, clt_frames, false);
291+
}
292+
277293
static int snd_pcm_plug_formats(const struct snd_mask *mask,
278294
snd_pcm_format_t format)
279295
{
@@ -630,7 +646,7 @@ snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *plug, st
630646
src_channels = dst_channels;
631647
plugin = next;
632648
}
633-
return snd_pcm_plug_client_size(plug, frames);
649+
return plug_client_size(plug, frames, true);
634650
}
635651

636652
snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *plug, struct snd_pcm_plugin_channel *dst_channels_final, snd_pcm_uframes_t size)
@@ -640,7 +656,7 @@ snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *plug, str
640656
snd_pcm_sframes_t frames = size;
641657
int err;
642658

643-
frames = snd_pcm_plug_slave_size(plug, frames);
659+
frames = plug_slave_size(plug, frames, true);
644660
if (frames < 0)
645661
return frames;
646662

0 commit comments

Comments
 (0)