| From 2065e6aa03a1619956e6c8e59289e66d0049cf7d Mon Sep 17 00:00:00 2001 |
| From: Charles Keepax <ckeepax@opensource.cirrus.com> |
| Date: Mon, 22 Jul 2019 10:24:34 +0100 |
| Subject: ALSA: compress: Prevent bypasses of set_params |
| |
| [ Upstream commit 26c3f1542f5064310ad26794c09321780d00c57d ] |
| |
| Currently, whilst in SNDRV_PCM_STATE_OPEN it is possible to call |
| snd_compr_stop, snd_compr_drain and snd_compr_partial_drain, which |
| allow a transition to SNDRV_PCM_STATE_SETUP. The stream should |
| only be able to move to the setup state once it has received a |
| SNDRV_COMPRESS_SET_PARAMS ioctl. Fix this issue by not allowing |
| those ioctls whilst in the open state. |
| |
| Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com> |
| Acked-by: Vinod Koul <vkoul@kernel.org> |
| Signed-off-by: Takashi Iwai <tiwai@suse.de> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| sound/core/compress_offload.c | 30 ++++++++++++++++++++++++------ |
| 1 file changed, 24 insertions(+), 6 deletions(-) |
| |
| diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c |
| index cf1317546b0ff..1538fbc7562b8 100644 |
| --- a/sound/core/compress_offload.c |
| +++ b/sound/core/compress_offload.c |
| @@ -712,9 +712,15 @@ static int snd_compr_stop(struct snd_compr_stream *stream) |
| { |
| int retval; |
| |
| - if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED || |
| - stream->runtime->state == SNDRV_PCM_STATE_SETUP) |
| + switch (stream->runtime->state) { |
| + case SNDRV_PCM_STATE_OPEN: |
| + case SNDRV_PCM_STATE_SETUP: |
| + case SNDRV_PCM_STATE_PREPARED: |
| return -EPERM; |
| + default: |
| + break; |
| + } |
| + |
| retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP); |
| if (!retval) { |
| snd_compr_drain_notify(stream); |
| @@ -802,9 +808,14 @@ static int snd_compr_drain(struct snd_compr_stream *stream) |
| { |
| int retval; |
| |
| - if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED || |
| - stream->runtime->state == SNDRV_PCM_STATE_SETUP) |
| + switch (stream->runtime->state) { |
| + case SNDRV_PCM_STATE_OPEN: |
| + case SNDRV_PCM_STATE_SETUP: |
| + case SNDRV_PCM_STATE_PREPARED: |
| return -EPERM; |
| + default: |
| + break; |
| + } |
| |
| retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN); |
| if (retval) { |
| @@ -841,9 +852,16 @@ static int snd_compr_next_track(struct snd_compr_stream *stream) |
| static int snd_compr_partial_drain(struct snd_compr_stream *stream) |
| { |
| int retval; |
| - if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED || |
| - stream->runtime->state == SNDRV_PCM_STATE_SETUP) |
| + |
| + switch (stream->runtime->state) { |
| + case SNDRV_PCM_STATE_OPEN: |
| + case SNDRV_PCM_STATE_SETUP: |
| + case SNDRV_PCM_STATE_PREPARED: |
| return -EPERM; |
| + default: |
| + break; |
| + } |
| + |
| /* stream can be drained only when next track has been signalled */ |
| if (stream->next_track == false) |
| return -EPERM; |
| -- |
| 2.20.1 |
| |