[alsa-devel] [PATCH] ALSA: pcm: Fill silence on buffers at hw_params
Takashi Iwai
tiwai at suse.de
Tue Dec 10 18:25:39 CET 2019
On Tue, 10 Dec 2019 14:02:19 +0100,
Takashi Iwai wrote:
>
> The current PCM code doesn't initialize explicitly the buffers
> allocated for PCM streams, hence it might leak some uninitialized
> kernel data by mmapping or reading the buffer before actually reading
> or writing.
>
> Since this is a common problem, let's initialize the data on the
> buffers each hw_params properly. For that, an existing helper
> function is exposed as snd_pcm_fill_silence_frames() and call it from
> snd_pcm_hw_params().
>
> Reported-and-tested-by: Lionel Koenig <lionel.koenig at gmail.com>
> Cc: <stable at vger.kernel.org>
> Signed-off-by: Takashi Iwai <tiwai at suse.de>
On the second thought, this use of fill_silence ops might have some
side-effect on the drivers that do actually transfer stream data by
that ops. So I dropped this patch again.
Will submit the revised patch later. Sorry for the trouble.
Takashi
> ---
> sound/core/pcm_lib.c | 13 ++++---------
> sound/core/pcm_local.h | 2 ++
> sound/core/pcm_native.c | 3 +++
> 3 files changed, 9 insertions(+), 9 deletions(-)
>
> diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
> index 2236b5e0c1f2..3c63324b8bb7 100644
> --- a/sound/core/pcm_lib.c
> +++ b/sound/core/pcm_lib.c
> @@ -30,9 +30,6 @@
> #define trace_applptr(substream, prev, curr)
> #endif
>
> -static int fill_silence_frames(struct snd_pcm_substream *substream,
> - snd_pcm_uframes_t off, snd_pcm_uframes_t frames);
> -
> /*
> * fill ring buffer with silence
> * runtime->silence_start: starting pointer to silence area
> @@ -100,7 +97,7 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
> ofs = runtime->silence_start % runtime->buffer_size;
> while (frames > 0) {
> transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames;
> - err = fill_silence_frames(substream, ofs, transfer);
> + err = snd_pcm_fill_silence_frames(substream, ofs, transfer);
> snd_BUG_ON(err < 0);
> runtime->silence_filled += transfer;
> frames -= transfer;
> @@ -1945,8 +1942,6 @@ static int fill_silence(struct snd_pcm_substream *substream, int channel,
> {
> struct snd_pcm_runtime *runtime = substream->runtime;
>
> - if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
> - return 0;
> if (substream->ops->fill_silence)
> return substream->ops->fill_silence(substream, channel,
> hwoff, bytes);
> @@ -2030,10 +2025,10 @@ static int noninterleaved_copy(struct snd_pcm_substream *substream,
> }
>
> /* fill silence on the given buffer position;
> - * called from snd_pcm_playback_silence()
> + * called from snd_pcm_playback_silence() and snd_pcm_hw_params()
> */
> -static int fill_silence_frames(struct snd_pcm_substream *substream,
> - snd_pcm_uframes_t off, snd_pcm_uframes_t frames)
> +int snd_pcm_fill_silence_frames(struct snd_pcm_substream *substream,
> + snd_pcm_uframes_t off, snd_pcm_uframes_t frames)
> {
> if (substream->runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
> substream->runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED)
> diff --git a/sound/core/pcm_local.h b/sound/core/pcm_local.h
> index 384efd002984..ac4f455b1fff 100644
> --- a/sound/core/pcm_local.h
> +++ b/sound/core/pcm_local.h
> @@ -34,6 +34,8 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream);
>
> void snd_pcm_playback_silence(struct snd_pcm_substream *substream,
> snd_pcm_uframes_t new_hw_ptr);
> +int snd_pcm_fill_silence_frames(struct snd_pcm_substream *substream,
> + snd_pcm_uframes_t off, snd_pcm_uframes_t frames);
>
> static inline snd_pcm_uframes_t
> snd_pcm_avail(struct snd_pcm_substream *substream)
> diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
> index 1fe581167b7b..d6f270c639b4 100644
> --- a/sound/core/pcm_native.c
> +++ b/sound/core/pcm_native.c
> @@ -739,6 +739,9 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
> while (runtime->boundary * 2 <= LONG_MAX - runtime->buffer_size)
> runtime->boundary *= 2;
>
> + /* clear the buffer once for avoiding information leaks */
> + snd_pcm_fill_silence_frames(substream, 0, runtime->period_size);
> +
> snd_pcm_timer_resolution_change(substream);
> snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP);
>
> --
> 2.16.4
>
More information about the Alsa-devel
mailing list