]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.18-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 30 Mar 2019 09:58:41 +0000 (10:58 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 30 Mar 2019 09:58:41 +0000 (10:58 +0100)
added patches:
alsa-pcm-don-t-suspend-stream-in-unrecoverable-pcm-state.patch
alsa-pcm-fix-possible-oob-access-in-pcm-oss-plugins.patch

queue-3.18/alsa-pcm-don-t-suspend-stream-in-unrecoverable-pcm-state.patch [new file with mode: 0644]
queue-3.18/alsa-pcm-fix-possible-oob-access-in-pcm-oss-plugins.patch [new file with mode: 0644]
queue-3.18/series

diff --git a/queue-3.18/alsa-pcm-don-t-suspend-stream-in-unrecoverable-pcm-state.patch b/queue-3.18/alsa-pcm-don-t-suspend-stream-in-unrecoverable-pcm-state.patch
new file mode 100644 (file)
index 0000000..29c55f5
--- /dev/null
@@ -0,0 +1,70 @@
+From 113ce08109f8e3b091399e7cc32486df1cff48e7 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 25 Mar 2019 10:38:58 +0100
+Subject: ALSA: pcm: Don't suspend stream in unrecoverable PCM state
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 113ce08109f8e3b091399e7cc32486df1cff48e7 upstream.
+
+Currently PCM core sets each opened stream forcibly to SUSPENDED state
+via snd_pcm_suspend_all() call, and the user-space is responsible for
+re-triggering the resume manually either via snd_pcm_resume() or
+prepare call.  The scheme works fine usually, but there are corner
+cases where the stream can't be resumed by that call: the streams
+still in OPEN state before finishing hw_params.  When they are
+suspended, user-space cannot perform resume or prepare because they
+haven't been set up yet.  The only possible recovery is to re-open the
+device, which isn't nice at all.  Similarly, when a stream is in
+DISCONNECTED state, it makes no sense to change it to SUSPENDED
+state.  Ditto for in SETUP state; which you can re-prepare directly.
+
+So, this patch addresses these issues by filtering the PCM streams to
+be suspended by checking the PCM state.  When a stream is in either
+OPEN, SETUP or DISCONNECTED as well as already SUSPENDED, the suspend
+action is skipped.
+
+To be noted, this problem was originally reported for the PCM runtime
+PM on HD-audio.  And, the runtime PM problem itself was already
+addressed (although not intended) by the code refactoring commits
+3d21ef0b49f8 ("ALSA: pcm: Suspend streams globally via device type PM
+ops") and 17bc4815de58 ("ALSA: pci: Remove superfluous
+snd_pcm_suspend*() calls").  These commits eliminated the
+snd_pcm_suspend*() calls from the runtime PM suspend callback code
+path, hence the racy OPEN state won't appear while runtime PM.
+(FWIW, the race window is between snd_pcm_open_substream() and the
+first power up in azx_pcm_open().)
+
+Although the runtime PM issue was already "fixed", the same problem is
+still present for the system PM, hence this patch is still needed.
+And for stable trees, this patch alone should suffice for fixing the
+runtime PM problem, too.
+
+Reported-and-tested-by: Jon Hunter <jonathanh@nvidia.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/pcm_native.c |    9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -1225,8 +1225,15 @@ static int snd_pcm_pause(struct snd_pcm_
+ static int snd_pcm_pre_suspend(struct snd_pcm_substream *substream, int state)
+ {
+       struct snd_pcm_runtime *runtime = substream->runtime;
+-      if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
++      switch (runtime->status->state) {
++      case SNDRV_PCM_STATE_SUSPENDED:
+               return -EBUSY;
++      /* unresumable PCM state; return -EBUSY for skipping suspend */
++      case SNDRV_PCM_STATE_OPEN:
++      case SNDRV_PCM_STATE_SETUP:
++      case SNDRV_PCM_STATE_DISCONNECTED:
++              return -EBUSY;
++      }
+       runtime->trigger_master = substream;
+       return 0;
+ }
diff --git a/queue-3.18/alsa-pcm-fix-possible-oob-access-in-pcm-oss-plugins.patch b/queue-3.18/alsa-pcm-fix-possible-oob-access-in-pcm-oss-plugins.patch
new file mode 100644 (file)
index 0000000..c6b7fbf
--- /dev/null
@@ -0,0 +1,104 @@
+From ca0214ee2802dd47239a4e39fb21c5b00ef61b22 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 22 Mar 2019 16:00:54 +0100
+Subject: ALSA: pcm: Fix possible OOB access in PCM oss plugins
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit ca0214ee2802dd47239a4e39fb21c5b00ef61b22 upstream.
+
+The PCM OSS emulation converts and transfers the data on the fly via
+"plugins".  The data is converted over the dynamically allocated
+buffer for each plugin, and recently syzkaller caught OOB in this
+flow.
+
+Although the bisection by syzbot pointed out to the commit
+65766ee0bf7f ("ALSA: oss: Use kvzalloc() for local buffer
+allocations"), this is merely a commit to replace vmalloc() with
+kvmalloc(), hence it can't be the cause.  The further debug action
+revealed that this happens in the case where a slave PCM doesn't
+support only the stereo channels while the OSS stream is set up for a
+mono channel.  Below is a brief explanation:
+
+At each OSS parameter change, the driver sets up the PCM hw_params
+again in snd_pcm_oss_change_params_lock().  This is also the place
+where plugins are created and local buffers are allocated.  The
+problem is that the plugins are created before the final hw_params is
+determined.  Namely, two snd_pcm_hw_param_near() calls for setting the
+period size and periods may influence on the final result of channels,
+rates, etc, too, while the current code has already created plugins
+beforehand with the premature values.  So, the plugin believes that
+channels=1, while the actual I/O is with channels=2, which makes the
+driver reading/writing over the allocated buffer size.
+
+The fix is simply to move the plugin allocation code after the final
+hw_params call.
+
+Reported-by: syzbot+d4503ae45b65c5bc1194@syzkaller.appspotmail.com
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/oss/pcm_oss.c |   43 ++++++++++++++++++++++---------------------
+ 1 file changed, 22 insertions(+), 21 deletions(-)
+
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -951,6 +951,28 @@ static int snd_pcm_oss_change_params_loc
+       oss_frame_size = snd_pcm_format_physical_width(params_format(params)) *
+                        params_channels(params) / 8;
++      err = snd_pcm_oss_period_size(substream, params, sparams);
++      if (err < 0)
++              goto failure;
++
++      n = snd_pcm_plug_slave_size(substream, runtime->oss.period_bytes / oss_frame_size);
++      err = snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, n, NULL);
++      if (err < 0)
++              goto failure;
++
++      err = snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_PERIODS,
++                                   runtime->oss.periods, NULL);
++      if (err < 0)
++              goto failure;
++
++      snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
++
++      err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_HW_PARAMS, sparams);
++      if (err < 0) {
++              pcm_dbg(substream->pcm, "HW_PARAMS failed: %i\n", err);
++              goto failure;
++      }
++
+ #ifdef CONFIG_SND_PCM_OSS_PLUGINS
+       snd_pcm_oss_plugin_clear(substream);
+       if (!direct) {
+@@ -985,27 +1007,6 @@ static int snd_pcm_oss_change_params_loc
+       }
+ #endif
+-      err = snd_pcm_oss_period_size(substream, params, sparams);
+-      if (err < 0)
+-              goto failure;
+-
+-      n = snd_pcm_plug_slave_size(substream, runtime->oss.period_bytes / oss_frame_size);
+-      err = snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, n, NULL);
+-      if (err < 0)
+-              goto failure;
+-
+-      err = snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_PERIODS,
+-                                   runtime->oss.periods, NULL);
+-      if (err < 0)
+-              goto failure;
+-
+-      snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
+-
+-      if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_HW_PARAMS, sparams)) < 0) {
+-              pcm_dbg(substream->pcm, "HW_PARAMS failed: %i\n", err);
+-              goto failure;
+-      }
+-
+       if (runtime->oss.trigger) {
+               sw_params->start_threshold = 1;
+       } else {
index c85633a813df68bda00e571010a9a94747a7d619..537cd1d23dd04dac69a3fecb7217ae9546835a8c 100644 (file)
@@ -34,3 +34,5 @@ packets-always-register-packet-sk-in-the-same-order.patch
 tcp-do-not-use-ipv6-header-for-ipv4-flow.patch
 sctp-get-sctphdr-by-offset-in-sctp_compute_cksum.patch
 mac8390-fix-mmio-access-size-probe.patch
+alsa-pcm-fix-possible-oob-access-in-pcm-oss-plugins.patch
+alsa-pcm-don-t-suspend-stream-in-unrecoverable-pcm-state.patch