Skip to content

Commit 93a81ca

Browse files
committed
ALSA: pcm: Fix race of buffer access at PCM OSS layer
The PCM OSS layer tries to clear the buffer with the silence data at initialization (or reconfiguration) of a stream with the explicit call of snd_pcm_format_set_silence() with runtime->dma_area. But this may lead to a UAF because the accessed runtime->dma_area might be freed concurrently, as it's performed outside the PCM ops. For avoiding it, move the code into the PCM core and perform it inside the buffer access lock, so that it won't be changed during the operation. Reported-by: syzbot+32d4647f551007595173@syzkaller.appspotmail.com Closes: https://lore.kernel.org/68164d8e.050a0220.11da1b.0019.GAE@google.com Cc: <stable@vger.kernel.org> Link: https://patch.msgid.link/20250516080817.20068-1-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent 7b9938a commit 93a81ca

File tree

3 files changed

+14
-2
lines changed

3 files changed

+14
-2
lines changed

include/sound/pcm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,6 +1404,8 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, struct vm_area_s
14041404
#define snd_pcm_lib_mmap_iomem NULL
14051405
#endif
14061406

1407+
void snd_pcm_runtime_buffer_set_silence(struct snd_pcm_runtime *runtime);
1408+
14071409
/**
14081410
* snd_pcm_limit_isa_dma_size - Get the max size fitting with ISA DMA transfer
14091411
* @dma: DMA number

sound/core/oss/pcm_oss.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,8 +1074,7 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
10741074
runtime->oss.params = 0;
10751075
runtime->oss.prepare = 1;
10761076
runtime->oss.buffer_used = 0;
1077-
if (runtime->dma_area)
1078-
snd_pcm_format_set_silence(runtime->format, runtime->dma_area, bytes_to_samples(runtime, runtime->dma_bytes));
1077+
snd_pcm_runtime_buffer_set_silence(runtime);
10791078

10801079
runtime->oss.period_frames = snd_pcm_alsa_frames(substream, oss_period_size);
10811080

sound/core/pcm_native.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,17 @@ static void snd_pcm_buffer_access_unlock(struct snd_pcm_runtime *runtime)
723723
atomic_inc(&runtime->buffer_accessing);
724724
}
725725

726+
/* fill the PCM buffer with the current silence format; called from pcm_oss.c */
727+
void snd_pcm_runtime_buffer_set_silence(struct snd_pcm_runtime *runtime)
728+
{
729+
snd_pcm_buffer_access_lock(runtime);
730+
if (runtime->dma_area)
731+
snd_pcm_format_set_silence(runtime->format, runtime->dma_area,
732+
bytes_to_samples(runtime, runtime->dma_bytes));
733+
snd_pcm_buffer_access_unlock(runtime);
734+
}
735+
EXPORT_SYMBOL_GPL(snd_pcm_runtime_buffer_set_silence);
736+
726737
#if IS_ENABLED(CONFIG_SND_PCM_OSS)
727738
#define is_oss_stream(substream) ((substream)->oss.oss)
728739
#else

0 commit comments

Comments
 (0)