]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.16-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 20 Apr 2018 16:29:14 +0000 (18:29 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 20 Apr 2018 16:29:14 +0000 (18:29 +0200)
added patches:
alsa-pcm-avoid-potential-races-between-oss-ioctls-and-read-write.patch
alsa-pcm-fix-endless-loop-for-xrun-recovery-in-oss-emulation.patch
alsa-pcm-fix-mutex-unbalance-in-oss-emulation-ioctls.patch
alsa-pcm-fix-uaf-at-pcm-release-via-pcm-timer-access.patch
alsa-pcm-return-ebusy-for-oss-ioctls-changing-busy-streams.patch
cxl-fix-possible-deadlock-when-processing-page-faults-from-cxllib.patch
dm-backfill-abnormal-io-support-to-non-splitting-io-submission.patch
dm-crypt-limit-the-number-of-allocated-pages.patch
dm-raid-fix-nosync-status.patch
dmaengine-at_xdmac-fix-rare-residue-corruption.patch
drivers-infiniband-core-verbs.c-fix-build-with-gcc-4.4.4.patch
drivers-infiniband-ulp-srpt-ib_srpt.c-fix-build-with-gcc-4.4.4.patch
ib-srp-fix-completion-vector-assignment-algorithm.patch
ib-srp-fix-srp_abort.patch
ib-srpt-fix-an-out-of-bounds-stack-access-in-srpt_zerolength_write.patch
libnvdimm-dimm-fix-dpa-reservation-vs-uninitialized-label-area.patch
libnvdimm-namespace-use-a-safe-lookup-for-dimm-device-name.patch
rdma-core-avoid-that-ib_drain_qp-triggers-an-out-of-bounds-stack-access.patch
rdma-mlx5-protect-from-null-pointer-derefence.patch
rdma-rxe-fix-an-out-of-bounds-read.patch
rdma-ucma-don-t-allow-setting-rdma_option_ib_path-without-an-rdma-device.patch
tpm-self-test-failure-should-not-cause-suspend-to-fail.patch
vsprintf-do-not-preprocess-non-dereferenced-pointers-for-bprintf-px-and-pk.patch
xprtrdma-fix-corner-cases-when-handling-device-removal.patch
xprtrdma-fix-latency-regression-on-numa-nfs-rdma-clients.patch

26 files changed:
queue-4.16/alsa-pcm-avoid-potential-races-between-oss-ioctls-and-read-write.patch [new file with mode: 0644]
queue-4.16/alsa-pcm-fix-endless-loop-for-xrun-recovery-in-oss-emulation.patch [new file with mode: 0644]
queue-4.16/alsa-pcm-fix-mutex-unbalance-in-oss-emulation-ioctls.patch [new file with mode: 0644]
queue-4.16/alsa-pcm-fix-uaf-at-pcm-release-via-pcm-timer-access.patch [new file with mode: 0644]
queue-4.16/alsa-pcm-return-ebusy-for-oss-ioctls-changing-busy-streams.patch [new file with mode: 0644]
queue-4.16/cxl-fix-possible-deadlock-when-processing-page-faults-from-cxllib.patch [new file with mode: 0644]
queue-4.16/dm-backfill-abnormal-io-support-to-non-splitting-io-submission.patch [new file with mode: 0644]
queue-4.16/dm-crypt-limit-the-number-of-allocated-pages.patch [new file with mode: 0644]
queue-4.16/dm-raid-fix-nosync-status.patch [new file with mode: 0644]
queue-4.16/dmaengine-at_xdmac-fix-rare-residue-corruption.patch [new file with mode: 0644]
queue-4.16/drivers-infiniband-core-verbs.c-fix-build-with-gcc-4.4.4.patch [new file with mode: 0644]
queue-4.16/drivers-infiniband-ulp-srpt-ib_srpt.c-fix-build-with-gcc-4.4.4.patch [new file with mode: 0644]
queue-4.16/ib-srp-fix-completion-vector-assignment-algorithm.patch [new file with mode: 0644]
queue-4.16/ib-srp-fix-srp_abort.patch [new file with mode: 0644]
queue-4.16/ib-srpt-fix-an-out-of-bounds-stack-access-in-srpt_zerolength_write.patch [new file with mode: 0644]
queue-4.16/libnvdimm-dimm-fix-dpa-reservation-vs-uninitialized-label-area.patch [new file with mode: 0644]
queue-4.16/libnvdimm-namespace-use-a-safe-lookup-for-dimm-device-name.patch [new file with mode: 0644]
queue-4.16/rdma-core-avoid-that-ib_drain_qp-triggers-an-out-of-bounds-stack-access.patch [new file with mode: 0644]
queue-4.16/rdma-mlx5-protect-from-null-pointer-derefence.patch [new file with mode: 0644]
queue-4.16/rdma-rxe-fix-an-out-of-bounds-read.patch [new file with mode: 0644]
queue-4.16/rdma-ucma-don-t-allow-setting-rdma_option_ib_path-without-an-rdma-device.patch [new file with mode: 0644]
queue-4.16/series
queue-4.16/tpm-self-test-failure-should-not-cause-suspend-to-fail.patch [new file with mode: 0644]
queue-4.16/vsprintf-do-not-preprocess-non-dereferenced-pointers-for-bprintf-px-and-pk.patch [new file with mode: 0644]
queue-4.16/xprtrdma-fix-corner-cases-when-handling-device-removal.patch [new file with mode: 0644]
queue-4.16/xprtrdma-fix-latency-regression-on-numa-nfs-rdma-clients.patch [new file with mode: 0644]

diff --git a/queue-4.16/alsa-pcm-avoid-potential-races-between-oss-ioctls-and-read-write.patch b/queue-4.16/alsa-pcm-avoid-potential-races-between-oss-ioctls-and-read-write.patch
new file mode 100644 (file)
index 0000000..e4ff5db
--- /dev/null
@@ -0,0 +1,376 @@
+From 02a5d6925cd34c3b774bdb8eefb057c40a30e870 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Thu, 22 Mar 2018 18:10:14 +0100
+Subject: ALSA: pcm: Avoid potential races between OSS ioctls and read/write
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 02a5d6925cd34c3b774bdb8eefb057c40a30e870 upstream.
+
+Although we apply the params_lock mutex to the whole read and write
+operations as well as snd_pcm_oss_change_params(), we may still face
+some races.
+
+First off, the params_lock is taken inside the read and write loop.
+This is intentional for avoiding the too long locking, but it allows
+the in-between parameter change, which might lead to invalid
+pointers.  We check the readiness of the stream and set up via
+snd_pcm_oss_make_ready() at the beginning of read and write, but it's
+called only once, by assuming that it remains ready in the rest.
+
+Second, many ioctls that may change the actual parameters
+(i.e. setting runtime->oss.params=1) aren't protected, hence they can
+be processed in a half-baked state.
+
+This patch is an attempt to plug these holes.  The stream readiness
+check is moved inside the read/write inner loop, so that the stream is
+always set up in a proper state before further processing.  Also, each
+ioctl that may change the parameter is wrapped with the params_lock
+for avoiding the races.
+
+The issues were triggered by syzkaller in a few different scenarios,
+particularly the one below appearing as GPF in loopback_pos_update.
+
+Reported-by: syzbot+c4227aec125487ec3efa@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 |  134 +++++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 106 insertions(+), 28 deletions(-)
+
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -823,8 +823,8 @@ static int choose_rate(struct snd_pcm_su
+       return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL);
+ }
+-static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream,
+-                                   bool trylock)
++/* call with params_lock held */
++static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
+ {
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct snd_pcm_hw_params *params, *sparams;
+@@ -838,11 +838,8 @@ static int snd_pcm_oss_change_params(str
+       const struct snd_mask *sformat_mask;
+       struct snd_mask mask;
+-      if (trylock) {
+-              if (!(mutex_trylock(&runtime->oss.params_lock)))
+-                      return -EAGAIN;
+-      } else if (mutex_lock_interruptible(&runtime->oss.params_lock))
+-              return -ERESTARTSYS;
++      if (!runtime->oss.params)
++              return 0;
+       sw_params = kzalloc(sizeof(*sw_params), GFP_KERNEL);
+       params = kmalloc(sizeof(*params), GFP_KERNEL);
+       sparams = kmalloc(sizeof(*sparams), GFP_KERNEL);
+@@ -1068,6 +1065,23 @@ failure:
+       kfree(sw_params);
+       kfree(params);
+       kfree(sparams);
++      return err;
++}
++
++/* this one takes the lock by itself */
++static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream,
++                                   bool trylock)
++{
++      struct snd_pcm_runtime *runtime = substream->runtime;
++      int err;
++
++      if (trylock) {
++              if (!(mutex_trylock(&runtime->oss.params_lock)))
++                      return -EAGAIN;
++      } else if (mutex_lock_interruptible(&runtime->oss.params_lock))
++              return -ERESTARTSYS;
++
++      err = snd_pcm_oss_change_params_locked(substream);
+       mutex_unlock(&runtime->oss.params_lock);
+       return err;
+ }
+@@ -1096,11 +1110,14 @@ static int snd_pcm_oss_get_active_substr
+       return 0;
+ }
++/* call with params_lock held */
+ static int snd_pcm_oss_prepare(struct snd_pcm_substream *substream)
+ {
+       int err;
+       struct snd_pcm_runtime *runtime = substream->runtime;
++      if (!runtime->oss.prepare)
++              return 0;
+       err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL);
+       if (err < 0) {
+               pcm_dbg(substream->pcm,
+@@ -1120,8 +1137,6 @@ static int snd_pcm_oss_make_ready(struct
+       struct snd_pcm_runtime *runtime;
+       int err;
+-      if (substream == NULL)
+-              return 0;
+       runtime = substream->runtime;
+       if (runtime->oss.params) {
+               err = snd_pcm_oss_change_params(substream, false);
+@@ -1129,6 +1144,29 @@ static int snd_pcm_oss_make_ready(struct
+                       return err;
+       }
+       if (runtime->oss.prepare) {
++              if (mutex_lock_interruptible(&runtime->oss.params_lock))
++                      return -ERESTARTSYS;
++              err = snd_pcm_oss_prepare(substream);
++              mutex_unlock(&runtime->oss.params_lock);
++              if (err < 0)
++                      return err;
++      }
++      return 0;
++}
++
++/* call with params_lock held */
++static int snd_pcm_oss_make_ready_locked(struct snd_pcm_substream *substream)
++{
++      struct snd_pcm_runtime *runtime;
++      int err;
++
++      runtime = substream->runtime;
++      if (runtime->oss.params) {
++              err = snd_pcm_oss_change_params_locked(substream);
++              if (err < 0)
++                      return err;
++      }
++      if (runtime->oss.prepare) {
+               err = snd_pcm_oss_prepare(substream);
+               if (err < 0)
+                       return err;
+@@ -1332,13 +1370,14 @@ static ssize_t snd_pcm_oss_write1(struct
+       if (atomic_read(&substream->mmap_count))
+               return -ENXIO;
+-      if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
+-              return tmp;
+       while (bytes > 0) {
+               if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
+                       tmp = -ERESTARTSYS;
+                       break;
+               }
++              tmp = snd_pcm_oss_make_ready_locked(substream);
++              if (tmp < 0)
++                      goto err;
+               if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
+                       tmp = bytes;
+                       if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes)
+@@ -1439,13 +1478,14 @@ static ssize_t snd_pcm_oss_read1(struct
+       if (atomic_read(&substream->mmap_count))
+               return -ENXIO;
+-      if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
+-              return tmp;
+       while (bytes > 0) {
+               if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
+                       tmp = -ERESTARTSYS;
+                       break;
+               }
++              tmp = snd_pcm_oss_make_ready_locked(substream);
++              if (tmp < 0)
++                      goto err;
+               if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
+                       if (runtime->oss.buffer_used == 0) {
+                               tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1);
+@@ -1501,10 +1541,12 @@ static int snd_pcm_oss_reset(struct snd_
+                       continue;
+               runtime = substream->runtime;
+               snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
++              mutex_lock(&runtime->oss.params_lock);
+               runtime->oss.prepare = 1;
+               runtime->oss.buffer_used = 0;
+               runtime->oss.prev_hw_ptr_period = 0;
+               runtime->oss.period_ptr = 0;
++              mutex_unlock(&runtime->oss.params_lock);
+       }
+       return 0;
+ }
+@@ -1590,9 +1632,10 @@ static int snd_pcm_oss_sync(struct snd_p
+                       goto __direct;
+               if ((err = snd_pcm_oss_make_ready(substream)) < 0)
+                       return err;
++              if (mutex_lock_interruptible(&runtime->oss.params_lock))
++                      return -ERESTARTSYS;
+               format = snd_pcm_oss_format_from(runtime->oss.format);
+               width = snd_pcm_format_physical_width(format);
+-              mutex_lock(&runtime->oss.params_lock);
+               if (runtime->oss.buffer_used > 0) {
+ #ifdef OSS_DEBUG
+                       pcm_dbg(substream->pcm, "sync: buffer_used\n");
+@@ -1643,7 +1686,9 @@ static int snd_pcm_oss_sync(struct snd_p
+               substream->f_flags = saved_f_flags;
+               if (err < 0)
+                       return err;
++              mutex_lock(&runtime->oss.params_lock);
+               runtime->oss.prepare = 1;
++              mutex_unlock(&runtime->oss.params_lock);
+       }
+       substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
+@@ -1654,8 +1699,10 @@ static int snd_pcm_oss_sync(struct snd_p
+               err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
+               if (err < 0)
+                       return err;
++              mutex_lock(&runtime->oss.params_lock);
+               runtime->oss.buffer_used = 0;
+               runtime->oss.prepare = 1;
++              mutex_unlock(&runtime->oss.params_lock);
+       }
+       return 0;
+ }
+@@ -1674,10 +1721,13 @@ static int snd_pcm_oss_set_rate(struct s
+                       rate = 1000;
+               else if (rate > 192000)
+                       rate = 192000;
++              if (mutex_lock_interruptible(&runtime->oss.params_lock))
++                      return -ERESTARTSYS;
+               if (runtime->oss.rate != rate) {
+                       runtime->oss.params = 1;
+                       runtime->oss.rate = rate;
+               }
++              mutex_unlock(&runtime->oss.params_lock);
+       }
+       return snd_pcm_oss_get_rate(pcm_oss_file);
+ }
+@@ -1705,10 +1755,13 @@ static int snd_pcm_oss_set_channels(stru
+               if (substream == NULL)
+                       continue;
+               runtime = substream->runtime;
++              if (mutex_lock_interruptible(&runtime->oss.params_lock))
++                      return -ERESTARTSYS;
+               if (runtime->oss.channels != channels) {
+                       runtime->oss.params = 1;
+                       runtime->oss.channels = channels;
+               }
++              mutex_unlock(&runtime->oss.params_lock);
+       }
+       return snd_pcm_oss_get_channels(pcm_oss_file);
+ }
+@@ -1794,10 +1847,13 @@ static int snd_pcm_oss_set_format(struct
+                       if (substream == NULL)
+                               continue;
+                       runtime = substream->runtime;
++                      if (mutex_lock_interruptible(&runtime->oss.params_lock))
++                              return -ERESTARTSYS;
+                       if (runtime->oss.format != format) {
+                               runtime->oss.params = 1;
+                               runtime->oss.format = format;
+                       }
++                      mutex_unlock(&runtime->oss.params_lock);
+               }
+       }
+       return snd_pcm_oss_get_format(pcm_oss_file);
+@@ -1817,8 +1873,6 @@ static int snd_pcm_oss_set_subdivide1(st
+ {
+       struct snd_pcm_runtime *runtime;
+-      if (substream == NULL)
+-              return 0;
+       runtime = substream->runtime;
+       if (subdivide == 0) {
+               subdivide = runtime->oss.subdivision;
+@@ -1842,9 +1896,16 @@ static int snd_pcm_oss_set_subdivide(str
+       for (idx = 1; idx >= 0; --idx) {
+               struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
++              struct snd_pcm_runtime *runtime;
++
+               if (substream == NULL)
+                       continue;
+-              if ((err = snd_pcm_oss_set_subdivide1(substream, subdivide)) < 0)
++              runtime = substream->runtime;
++              if (mutex_lock_interruptible(&runtime->oss.params_lock))
++                      return -ERESTARTSYS;
++              err = snd_pcm_oss_set_subdivide1(substream, subdivide);
++              mutex_unlock(&runtime->oss.params_lock);
++              if (err < 0)
+                       return err;
+       }
+       return err;
+@@ -1854,8 +1915,6 @@ static int snd_pcm_oss_set_fragment1(str
+ {
+       struct snd_pcm_runtime *runtime;
+-      if (substream == NULL)
+-              return 0;
+       runtime = substream->runtime;
+       if (runtime->oss.subdivision || runtime->oss.fragshift)
+               return -EINVAL;
+@@ -1875,9 +1934,16 @@ static int snd_pcm_oss_set_fragment(stru
+       for (idx = 1; idx >= 0; --idx) {
+               struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
++              struct snd_pcm_runtime *runtime;
++
+               if (substream == NULL)
+                       continue;
+-              if ((err = snd_pcm_oss_set_fragment1(substream, val)) < 0)
++              runtime = substream->runtime;
++              if (mutex_lock_interruptible(&runtime->oss.params_lock))
++                      return -ERESTARTSYS;
++              err = snd_pcm_oss_set_fragment1(substream, val);
++              mutex_unlock(&runtime->oss.params_lock);
++              if (err < 0)
+                       return err;
+       }
+       return err;
+@@ -1961,6 +2027,9 @@ static int snd_pcm_oss_set_trigger(struc
+       }
+               if (psubstream) {
+                       runtime = psubstream->runtime;
++              cmd = 0;
++              if (mutex_lock_interruptible(&runtime->oss.params_lock))
++                      return -ERESTARTSYS;
+               if (trigger & PCM_ENABLE_OUTPUT) {
+                       if (runtime->oss.trigger)
+                               goto _skip1;
+@@ -1978,13 +2047,19 @@ static int snd_pcm_oss_set_trigger(struc
+                       cmd = SNDRV_PCM_IOCTL_DROP;
+                       runtime->oss.prepare = 1;
+               }
+-              err = snd_pcm_kernel_ioctl(psubstream, cmd, NULL);
+-              if (err < 0)
+-                      return err;
+-      }
+  _skip1:
++              mutex_unlock(&runtime->oss.params_lock);
++              if (cmd) {
++                      err = snd_pcm_kernel_ioctl(psubstream, cmd, NULL);
++                      if (err < 0)
++                              return err;
++              }
++      }
+       if (csubstream) {
+                       runtime = csubstream->runtime;
++              cmd = 0;
++              if (mutex_lock_interruptible(&runtime->oss.params_lock))
++                      return -ERESTARTSYS;
+               if (trigger & PCM_ENABLE_INPUT) {
+                       if (runtime->oss.trigger)
+                               goto _skip2;
+@@ -1999,11 +2074,14 @@ static int snd_pcm_oss_set_trigger(struc
+                       cmd = SNDRV_PCM_IOCTL_DROP;
+                       runtime->oss.prepare = 1;
+               }
+-              err = snd_pcm_kernel_ioctl(csubstream, cmd, NULL);
+-              if (err < 0)
+-                      return err;
+-      }
+  _skip2:
++              mutex_unlock(&runtime->oss.params_lock);
++              if (cmd) {
++                      err = snd_pcm_kernel_ioctl(csubstream, cmd, NULL);
++                      if (err < 0)
++                              return err;
++              }
++      }
+       return 0;
+ }
diff --git a/queue-4.16/alsa-pcm-fix-endless-loop-for-xrun-recovery-in-oss-emulation.patch b/queue-4.16/alsa-pcm-fix-endless-loop-for-xrun-recovery-in-oss-emulation.patch
new file mode 100644 (file)
index 0000000..850f7fe
--- /dev/null
@@ -0,0 +1,53 @@
+From e15dc99dbb9cf99f6432e8e3c0b3a8f7a3403a86 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Sat, 7 Apr 2018 11:48:58 +0200
+Subject: ALSA: pcm: Fix endless loop for XRUN recovery in OSS emulation
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit e15dc99dbb9cf99f6432e8e3c0b3a8f7a3403a86 upstream.
+
+The commit 02a5d6925cd3 ("ALSA: pcm: Avoid potential races between OSS
+ioctls and read/write") split the PCM preparation code to a locked
+version, and it added a sanity check of runtime->oss.prepare flag
+along with the change.  This leaded to an endless loop when the stream
+gets XRUN: namely, snd_pcm_oss_write3() and co call
+snd_pcm_oss_prepare() without setting runtime->oss.prepare flag and
+the loop continues until the PCM state reaches to another one.
+
+As the function is supposed to execute the preparation
+unconditionally, drop the invalid state check there.
+
+The bug was triggered by syzkaller.
+
+Fixes: 02a5d6925cd3 ("ALSA: pcm: Avoid potential races between OSS ioctls and read/write")
+Reported-by: syzbot+150189c103427d31a053@syzkaller.appspotmail.com
+Reported-by: syzbot+7e3f31a52646f939c052@syzkaller.appspotmail.com
+Reported-by: syzbot+4f2016cf5185da7759dc@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 |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -1128,13 +1128,14 @@ static int snd_pcm_oss_get_active_substr
+ }
+ /* call with params_lock held */
++/* NOTE: this always call PREPARE unconditionally no matter whether
++ * runtime->oss.prepare is set or not
++ */
+ static int snd_pcm_oss_prepare(struct snd_pcm_substream *substream)
+ {
+       int err;
+       struct snd_pcm_runtime *runtime = substream->runtime;
+-      if (!runtime->oss.prepare)
+-              return 0;
+       err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL);
+       if (err < 0) {
+               pcm_dbg(substream->pcm,
diff --git a/queue-4.16/alsa-pcm-fix-mutex-unbalance-in-oss-emulation-ioctls.patch b/queue-4.16/alsa-pcm-fix-mutex-unbalance-in-oss-emulation-ioctls.patch
new file mode 100644 (file)
index 0000000..0643e1b
--- /dev/null
@@ -0,0 +1,169 @@
+From f6d297df4dd47ef949540e4a201230d0c5308325 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 27 Mar 2018 14:32:23 +0200
+Subject: ALSA: pcm: Fix mutex unbalance in OSS emulation ioctls
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit f6d297df4dd47ef949540e4a201230d0c5308325 upstream.
+
+The previous fix 40cab6e88cb0 ("ALSA: pcm: Return -EBUSY for OSS
+ioctls changing busy streams") introduced some mutex unbalance; the
+check of runtime->oss.rw_ref was inserted in a wrong place after the
+mutex lock.
+
+This patch fixes the inconsistency by rewriting with the helper
+functions to lock/unlock parameters with the stream check.
+
+Fixes: 40cab6e88cb0 ("ALSA: pcm: Return -EBUSY for OSS ioctls changing busy streams")
+Reported-by: Dan Carpenter <dan.carpenter@oracle.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 |   67 +++++++++++++++++++++++++++++------------------
+ 1 file changed, 42 insertions(+), 25 deletions(-)
+
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -823,6 +823,23 @@ static int choose_rate(struct snd_pcm_su
+       return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL);
+ }
++/* parameter locking: returns immediately if tried during streaming */
++static int lock_params(struct snd_pcm_runtime *runtime)
++{
++      if (mutex_lock_interruptible(&runtime->oss.params_lock))
++              return -ERESTARTSYS;
++      if (atomic_read(&runtime->oss.rw_ref)) {
++              mutex_unlock(&runtime->oss.params_lock);
++              return -EBUSY;
++      }
++      return 0;
++}
++
++static void unlock_params(struct snd_pcm_runtime *runtime)
++{
++      mutex_unlock(&runtime->oss.params_lock);
++}
++
+ /* call with params_lock held */
+ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
+ {
+@@ -1721,6 +1738,8 @@ static int snd_pcm_oss_set_rate(struct s
+       for (idx = 1; idx >= 0; --idx) {
+               struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
+               struct snd_pcm_runtime *runtime;
++              int err;
++
+               if (substream == NULL)
+                       continue;
+               runtime = substream->runtime;
+@@ -1728,15 +1747,14 @@ static int snd_pcm_oss_set_rate(struct s
+                       rate = 1000;
+               else if (rate > 192000)
+                       rate = 192000;
+-              if (mutex_lock_interruptible(&runtime->oss.params_lock))
+-                      return -ERESTARTSYS;
+-              if (atomic_read(&runtime->oss.rw_ref))
+-                      return -EBUSY;
++              err = lock_params(runtime);
++              if (err < 0)
++                      return err;
+               if (runtime->oss.rate != rate) {
+                       runtime->oss.params = 1;
+                       runtime->oss.rate = rate;
+               }
+-              mutex_unlock(&runtime->oss.params_lock);
++              unlock_params(runtime);
+       }
+       return snd_pcm_oss_get_rate(pcm_oss_file);
+ }
+@@ -1761,18 +1779,19 @@ static int snd_pcm_oss_set_channels(stru
+       for (idx = 1; idx >= 0; --idx) {
+               struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
+               struct snd_pcm_runtime *runtime;
++              int err;
++
+               if (substream == NULL)
+                       continue;
+               runtime = substream->runtime;
+-              if (mutex_lock_interruptible(&runtime->oss.params_lock))
+-                      return -ERESTARTSYS;
+-              if (atomic_read(&runtime->oss.rw_ref))
+-                      return -EBUSY;
++              err = lock_params(runtime);
++              if (err < 0)
++                      return err;
+               if (runtime->oss.channels != channels) {
+                       runtime->oss.params = 1;
+                       runtime->oss.channels = channels;
+               }
+-              mutex_unlock(&runtime->oss.params_lock);
++              unlock_params(runtime);
+       }
+       return snd_pcm_oss_get_channels(pcm_oss_file);
+ }
+@@ -1845,6 +1864,7 @@ static int snd_pcm_oss_get_formats(struc
+ static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int format)
+ {
+       int formats, idx;
++      int err;
+       
+       if (format != AFMT_QUERY) {
+               formats = snd_pcm_oss_get_formats(pcm_oss_file);
+@@ -1858,15 +1878,14 @@ static int snd_pcm_oss_set_format(struct
+                       if (substream == NULL)
+                               continue;
+                       runtime = substream->runtime;
+-                      if (atomic_read(&runtime->oss.rw_ref))
+-                              return -EBUSY;
+-                      if (mutex_lock_interruptible(&runtime->oss.params_lock))
+-                              return -ERESTARTSYS;
++                      err = lock_params(runtime);
++                      if (err < 0)
++                              return err;
+                       if (runtime->oss.format != format) {
+                               runtime->oss.params = 1;
+                               runtime->oss.format = format;
+                       }
+-                      mutex_unlock(&runtime->oss.params_lock);
++                      unlock_params(runtime);
+               }
+       }
+       return snd_pcm_oss_get_format(pcm_oss_file);
+@@ -1914,12 +1933,11 @@ static int snd_pcm_oss_set_subdivide(str
+               if (substream == NULL)
+                       continue;
+               runtime = substream->runtime;
+-              if (atomic_read(&runtime->oss.rw_ref))
+-                      return -EBUSY;
+-              if (mutex_lock_interruptible(&runtime->oss.params_lock))
+-                      return -ERESTARTSYS;
++              err = lock_params(runtime);
++              if (err < 0)
++                      return err;
+               err = snd_pcm_oss_set_subdivide1(substream, subdivide);
+-              mutex_unlock(&runtime->oss.params_lock);
++              unlock_params(runtime);
+               if (err < 0)
+                       return err;
+       }
+@@ -1954,12 +1972,11 @@ static int snd_pcm_oss_set_fragment(stru
+               if (substream == NULL)
+                       continue;
+               runtime = substream->runtime;
+-              if (atomic_read(&runtime->oss.rw_ref))
+-                      return -EBUSY;
+-              if (mutex_lock_interruptible(&runtime->oss.params_lock))
+-                      return -ERESTARTSYS;
++              err = lock_params(runtime);
++              if (err < 0)
++                      return err;
+               err = snd_pcm_oss_set_fragment1(substream, val);
+-              mutex_unlock(&runtime->oss.params_lock);
++              unlock_params(runtime);
+               if (err < 0)
+                       return err;
+       }
diff --git a/queue-4.16/alsa-pcm-fix-uaf-at-pcm-release-via-pcm-timer-access.patch b/queue-4.16/alsa-pcm-fix-uaf-at-pcm-release-via-pcm-timer-access.patch
new file mode 100644 (file)
index 0000000..0ab33b3
--- /dev/null
@@ -0,0 +1,59 @@
+From a820ccbe21e8ce8e86c39cd1d3bc8c7d1cbb949b Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 2 Apr 2018 22:41:43 +0200
+Subject: ALSA: pcm: Fix UAF at PCM release via PCM timer access
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit a820ccbe21e8ce8e86c39cd1d3bc8c7d1cbb949b upstream.
+
+The PCM runtime object is created and freed dynamically at PCM stream
+open / close time.  This is tracked via substream->runtime, and it's
+cleared at snd_pcm_detach_substream().
+
+The runtime object assignment is protected by PCM open_mutex, so for
+all PCM operations, it's safely handled.  However, each PCM substream
+provides also an ALSA timer interface, and user-space can access to
+this while closing a PCM substream.  This may eventually lead to a
+UAF, as snd_pcm_timer_resolution() tries to access the runtime while
+clearing it in other side.
+
+Fortunately, it's the only concurrent access from the PCM timer, and
+it merely reads runtime->timer_resolution field.  So, we can avoid the
+race by reordering kfree() and wrapping the substream->runtime
+clearance with the corresponding timer lock.
+
+Reported-by: syzbot+8e62ff4e07aa2ce87826@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/pcm.c |    8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/sound/core/pcm.c
++++ b/sound/core/pcm.c
+@@ -28,6 +28,7 @@
+ #include <sound/core.h>
+ #include <sound/minors.h>
+ #include <sound/pcm.h>
++#include <sound/timer.h>
+ #include <sound/control.h>
+ #include <sound/info.h>
+@@ -1054,8 +1055,13 @@ void snd_pcm_detach_substream(struct snd
+       snd_free_pages((void*)runtime->control,
+                      PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)));
+       kfree(runtime->hw_constraints.rules);
+-      kfree(runtime);
++      /* Avoid concurrent access to runtime via PCM timer interface */
++      if (substream->timer)
++              spin_lock_irq(&substream->timer->lock);
+       substream->runtime = NULL;
++      if (substream->timer)
++              spin_unlock_irq(&substream->timer->lock);
++      kfree(runtime);
+       put_pid(substream->pid);
+       substream->pid = NULL;
+       substream->pstr->substream_opened--;
diff --git a/queue-4.16/alsa-pcm-return-ebusy-for-oss-ioctls-changing-busy-streams.patch b/queue-4.16/alsa-pcm-return-ebusy-for-oss-ioctls-changing-busy-streams.patch
new file mode 100644 (file)
index 0000000..b38fd91
--- /dev/null
@@ -0,0 +1,182 @@
+From 40cab6e88cb0b6c56d3f30b7491a20e803f948f6 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 23 Mar 2018 08:03:26 +0100
+Subject: ALSA: pcm: Return -EBUSY for OSS ioctls changing busy streams
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 40cab6e88cb0b6c56d3f30b7491a20e803f948f6 upstream.
+
+OSS PCM stream management isn't modal but it allows ioctls issued at
+any time for changing the parameters.  In the previous hardening
+patch ("ALSA: pcm: Avoid potential races between OSS ioctls and
+read/write"), we covered these races and prevent the corruption by
+protecting the concurrent accesses via params_lock mutex.  However,
+this means that some ioctls that try to change the stream parameter
+(e.g. channels or format) would be blocked until the read/write
+finishes, and it may take really long.
+
+Basically changing the parameter while reading/writing is an invalid
+operation, hence it's even more user-friendly from the API POV if it
+returns -EBUSY in such a situation.
+
+This patch adds such checks in the relevant ioctls with the addition
+of read/write access refcount.
+
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/sound/pcm_oss.h  |    1 +
+ sound/core/oss/pcm_oss.c |   36 +++++++++++++++++++++++++++---------
+ 2 files changed, 28 insertions(+), 9 deletions(-)
+
+--- a/include/sound/pcm_oss.h
++++ b/include/sound/pcm_oss.h
+@@ -57,6 +57,7 @@ struct snd_pcm_oss_runtime {
+       char *buffer;                           /* vmallocated period */
+       size_t buffer_used;                     /* used length from period buffer */
+       struct mutex params_lock;
++      atomic_t rw_ref;                /* concurrent read/write accesses */
+ #ifdef CONFIG_SND_PCM_OSS_PLUGINS
+       struct snd_pcm_plugin *plugin_first;
+       struct snd_pcm_plugin *plugin_last;
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -1370,6 +1370,7 @@ static ssize_t snd_pcm_oss_write1(struct
+       if (atomic_read(&substream->mmap_count))
+               return -ENXIO;
++      atomic_inc(&runtime->oss.rw_ref);
+       while (bytes > 0) {
+               if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
+                       tmp = -ERESTARTSYS;
+@@ -1433,6 +1434,7 @@ static ssize_t snd_pcm_oss_write1(struct
+               }
+               tmp = 0;
+       }
++      atomic_dec(&runtime->oss.rw_ref);
+       return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
+ }
+@@ -1478,6 +1480,7 @@ static ssize_t snd_pcm_oss_read1(struct
+       if (atomic_read(&substream->mmap_count))
+               return -ENXIO;
++      atomic_inc(&runtime->oss.rw_ref);
+       while (bytes > 0) {
+               if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
+                       tmp = -ERESTARTSYS;
+@@ -1526,6 +1529,7 @@ static ssize_t snd_pcm_oss_read1(struct
+               }
+               tmp = 0;
+       }
++      atomic_dec(&runtime->oss.rw_ref);
+       return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
+ }
+@@ -1632,8 +1636,11 @@ static int snd_pcm_oss_sync(struct snd_p
+                       goto __direct;
+               if ((err = snd_pcm_oss_make_ready(substream)) < 0)
+                       return err;
+-              if (mutex_lock_interruptible(&runtime->oss.params_lock))
++              atomic_inc(&runtime->oss.rw_ref);
++              if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
++                      atomic_dec(&runtime->oss.rw_ref);
+                       return -ERESTARTSYS;
++              }
+               format = snd_pcm_oss_format_from(runtime->oss.format);
+               width = snd_pcm_format_physical_width(format);
+               if (runtime->oss.buffer_used > 0) {
+@@ -1645,10 +1652,8 @@ static int snd_pcm_oss_sync(struct snd_p
+                                                  runtime->oss.buffer + runtime->oss.buffer_used,
+                                                  size);
+                       err = snd_pcm_oss_sync1(substream, runtime->oss.period_bytes);
+-                      if (err < 0) {
+-                              mutex_unlock(&runtime->oss.params_lock);
+-                              return err;
+-                      }
++                      if (err < 0)
++                              goto unlock;
+               } else if (runtime->oss.period_ptr > 0) {
+ #ifdef OSS_DEBUG
+                       pcm_dbg(substream->pcm, "sync: period_ptr\n");
+@@ -1658,10 +1663,8 @@ static int snd_pcm_oss_sync(struct snd_p
+                                                  runtime->oss.buffer,
+                                                  size * 8 / width);
+                       err = snd_pcm_oss_sync1(substream, size);
+-                      if (err < 0) {
+-                              mutex_unlock(&runtime->oss.params_lock);
+-                              return err;
+-                      }
++                      if (err < 0)
++                              goto unlock;
+               }
+               /*
+                * The ALSA's period might be a bit large than OSS one.
+@@ -1675,7 +1678,11 @@ static int snd_pcm_oss_sync(struct snd_p
+                       else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
+                               snd_pcm_lib_writev(substream, NULL, size);
+               }
++unlock:
+               mutex_unlock(&runtime->oss.params_lock);
++              atomic_dec(&runtime->oss.rw_ref);
++              if (err < 0)
++                      return err;
+               /*
+                * finish sync: drain the buffer
+                */
+@@ -1723,6 +1730,8 @@ static int snd_pcm_oss_set_rate(struct s
+                       rate = 192000;
+               if (mutex_lock_interruptible(&runtime->oss.params_lock))
+                       return -ERESTARTSYS;
++              if (atomic_read(&runtime->oss.rw_ref))
++                      return -EBUSY;
+               if (runtime->oss.rate != rate) {
+                       runtime->oss.params = 1;
+                       runtime->oss.rate = rate;
+@@ -1757,6 +1766,8 @@ static int snd_pcm_oss_set_channels(stru
+               runtime = substream->runtime;
+               if (mutex_lock_interruptible(&runtime->oss.params_lock))
+                       return -ERESTARTSYS;
++              if (atomic_read(&runtime->oss.rw_ref))
++                      return -EBUSY;
+               if (runtime->oss.channels != channels) {
+                       runtime->oss.params = 1;
+                       runtime->oss.channels = channels;
+@@ -1847,6 +1858,8 @@ static int snd_pcm_oss_set_format(struct
+                       if (substream == NULL)
+                               continue;
+                       runtime = substream->runtime;
++                      if (atomic_read(&runtime->oss.rw_ref))
++                              return -EBUSY;
+                       if (mutex_lock_interruptible(&runtime->oss.params_lock))
+                               return -ERESTARTSYS;
+                       if (runtime->oss.format != format) {
+@@ -1901,6 +1914,8 @@ static int snd_pcm_oss_set_subdivide(str
+               if (substream == NULL)
+                       continue;
+               runtime = substream->runtime;
++              if (atomic_read(&runtime->oss.rw_ref))
++                      return -EBUSY;
+               if (mutex_lock_interruptible(&runtime->oss.params_lock))
+                       return -ERESTARTSYS;
+               err = snd_pcm_oss_set_subdivide1(substream, subdivide);
+@@ -1939,6 +1954,8 @@ static int snd_pcm_oss_set_fragment(stru
+               if (substream == NULL)
+                       continue;
+               runtime = substream->runtime;
++              if (atomic_read(&runtime->oss.rw_ref))
++                      return -EBUSY;
+               if (mutex_lock_interruptible(&runtime->oss.params_lock))
+                       return -ERESTARTSYS;
+               err = snd_pcm_oss_set_fragment1(substream, val);
+@@ -2333,6 +2350,7 @@ static void snd_pcm_oss_init_substream(s
+       runtime->oss.maxfrags = 0;
+       runtime->oss.subdivision = 0;
+       substream->pcm_release = snd_pcm_oss_release_substream;
++      atomic_set(&runtime->oss.rw_ref, 0);
+ }
+ static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
diff --git a/queue-4.16/cxl-fix-possible-deadlock-when-processing-page-faults-from-cxllib.patch b/queue-4.16/cxl-fix-possible-deadlock-when-processing-page-faults-from-cxllib.patch
new file mode 100644 (file)
index 0000000..5021244
--- /dev/null
@@ -0,0 +1,154 @@
+From ad7b4e8022b9864c075fe71e1328b1d25cad82f6 Mon Sep 17 00:00:00 2001
+From: Frederic Barrat <fbarrat@linux.vnet.ibm.com>
+Date: Tue, 3 Apr 2018 15:54:02 +0200
+Subject: cxl: Fix possible deadlock when processing page faults from cxllib
+
+From: Frederic Barrat <fbarrat@linux.vnet.ibm.com>
+
+commit ad7b4e8022b9864c075fe71e1328b1d25cad82f6 upstream.
+
+cxllib_handle_fault() is called by an external driver when it needs to
+have the host resolve page faults for a buffer. The buffer can cover
+several pages and VMAs. The function iterates over all the pages used
+by the buffer, based on the page size of the VMA.
+
+To ensure some stability while processing the faults, the thread T1
+grabs the mm->mmap_sem semaphore with read access (R1). However, when
+processing a page fault for a single page, one of the underlying
+functions, copro_handle_mm_fault(), also grabs the same semaphore with
+read access (R2). So the thread T1 takes the semaphore twice.
+
+If another thread T2 tries to access the semaphore in write mode W1
+(say, because it wants to allocate memory and calls 'brk'), then that
+thread T2 will have to wait because there's a reader (R1). If the
+thread T1 is processing a new page at that time, it won't get an
+automatic grant at R2, because there's now a writer thread
+waiting (T2). And we have a deadlock.
+
+The timeline is:
+1. thread T1 owns the semaphore with read access R1
+2. thread T2 requests write access W1 and waits
+3. thread T1 requests read access R2 and waits
+
+The fix is for the thread T1 to release the semaphore R1 once it got
+the information it needs from the current VMA. The address space/VMAs
+could evolve while T1 iterates over the full buffer, but in the
+unlikely case where T1 misses a page, the external driver will raise a
+new page fault when retrying the memory access.
+
+Fixes: 3ced8d730063 ("cxl: Export library to support IBM XSL")
+Cc: stable@vger.kernel.org # 4.13+
+Signed-off-by: Frederic Barrat <fbarrat@linux.vnet.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/misc/cxl/cxllib.c |   83 +++++++++++++++++++++++++++++-----------------
+ 1 file changed, 54 insertions(+), 29 deletions(-)
+
+--- a/drivers/misc/cxl/cxllib.c
++++ b/drivers/misc/cxl/cxllib.c
+@@ -208,49 +208,74 @@ int cxllib_get_PE_attributes(struct task
+ }
+ EXPORT_SYMBOL_GPL(cxllib_get_PE_attributes);
+-int cxllib_handle_fault(struct mm_struct *mm, u64 addr, u64 size, u64 flags)
++static int get_vma_info(struct mm_struct *mm, u64 addr,
++                      u64 *vma_start, u64 *vma_end,
++                      unsigned long *page_size)
+ {
+-      int rc;
+-      u64 dar;
+       struct vm_area_struct *vma = NULL;
+-      unsigned long page_size;
+-
+-      if (mm == NULL)
+-              return -EFAULT;
++      int rc = 0;
+       down_read(&mm->mmap_sem);
+       vma = find_vma(mm, addr);
+       if (!vma) {
+-              pr_err("Can't find vma for addr %016llx\n", addr);
+               rc = -EFAULT;
+               goto out;
+       }
+-      /* get the size of the pages allocated */
+-      page_size = vma_kernel_pagesize(vma);
++      *page_size = vma_kernel_pagesize(vma);
++      *vma_start = vma->vm_start;
++      *vma_end = vma->vm_end;
++out:
++      up_read(&mm->mmap_sem);
++      return rc;
++}
++
++int cxllib_handle_fault(struct mm_struct *mm, u64 addr, u64 size, u64 flags)
++{
++      int rc;
++      u64 dar, vma_start, vma_end;
++      unsigned long page_size;
+-      for (dar = (addr & ~(page_size - 1)); dar < (addr + size); dar += page_size) {
+-              if (dar < vma->vm_start || dar >= vma->vm_end) {
+-                      vma = find_vma(mm, addr);
+-                      if (!vma) {
+-                              pr_err("Can't find vma for addr %016llx\n", addr);
+-                              rc = -EFAULT;
+-                              goto out;
+-                      }
+-                      /* get the size of the pages allocated */
+-                      page_size = vma_kernel_pagesize(vma);
++      if (mm == NULL)
++              return -EFAULT;
++
++      /*
++       * The buffer we have to process can extend over several pages
++       * and may also cover several VMAs.
++       * We iterate over all the pages. The page size could vary
++       * between VMAs.
++       */
++      rc = get_vma_info(mm, addr, &vma_start, &vma_end, &page_size);
++      if (rc)
++              return rc;
++
++      for (dar = (addr & ~(page_size - 1)); dar < (addr + size);
++           dar += page_size) {
++              if (dar < vma_start || dar >= vma_end) {
++                      /*
++                       * We don't hold the mm->mmap_sem semaphore
++                       * while iterating, since the semaphore is
++                       * required by one of the lower-level page
++                       * fault processing functions and it could
++                       * create a deadlock.
++                       *
++                       * It means the VMAs can be altered between 2
++                       * loop iterations and we could theoretically
++                       * miss a page (however unlikely). But that's
++                       * not really a problem, as the driver will
++                       * retry access, get another page fault on the
++                       * missing page and call us again.
++                       */
++                      rc = get_vma_info(mm, dar, &vma_start, &vma_end,
++                                      &page_size);
++                      if (rc)
++                              return rc;
+               }
+               rc = cxl_handle_mm_fault(mm, flags, dar);
+-              if (rc) {
+-                      pr_err("cxl_handle_mm_fault failed %d", rc);
+-                      rc = -EFAULT;
+-                      goto out;
+-              }
++              if (rc)
++                      return -EFAULT;
+       }
+-      rc = 0;
+-out:
+-      up_read(&mm->mmap_sem);
+-      return rc;
++      return 0;
+ }
+ EXPORT_SYMBOL_GPL(cxllib_handle_fault);
diff --git a/queue-4.16/dm-backfill-abnormal-io-support-to-non-splitting-io-submission.patch b/queue-4.16/dm-backfill-abnormal-io-support-to-non-splitting-io-submission.patch
new file mode 100644 (file)
index 0000000..9e5f844
--- /dev/null
@@ -0,0 +1,79 @@
+From 0519c71e8d461ac3ef9a555bb7339243c9128d37 Mon Sep 17 00:00:00 2001
+From: Mike Snitzer <snitzer@redhat.com>
+Date: Mon, 26 Mar 2018 11:49:16 -0400
+Subject: dm: backfill abnormal IO support to non-splitting IO submission
+
+From: Mike Snitzer <snitzer@redhat.com>
+
+commit 0519c71e8d461ac3ef9a555bb7339243c9128d37 upstream.
+
+Otherwise, these abnormal IOs would be sent to the DM target
+regardless of whether the target advertised support for them.
+
+Factor out __process_abnormal_io() from __split_and_process_non_flush()
+so that discards, write same, etc may be conditionally processed.
+
+Fixes: 978e51ba3 ("dm: optimize bio-based NVMe IO submission")
+Cc: stable@vger.kernel.org # 4.16
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/dm.c |   30 +++++++++++++++++++++++-------
+ 1 file changed, 23 insertions(+), 7 deletions(-)
+
+--- a/drivers/md/dm.c
++++ b/drivers/md/dm.c
+@@ -1477,6 +1477,23 @@ static int __send_write_zeroes(struct cl
+       return __send_changing_extent_only(ci, ti, get_num_write_zeroes_bios, NULL);
+ }
++static bool __process_abnormal_io(struct clone_info *ci, struct dm_target *ti,
++                                int *result)
++{
++      struct bio *bio = ci->bio;
++
++      if (bio_op(bio) == REQ_OP_DISCARD)
++              *result = __send_discard(ci, ti);
++      else if (bio_op(bio) == REQ_OP_WRITE_SAME)
++              *result = __send_write_same(ci, ti);
++      else if (bio_op(bio) == REQ_OP_WRITE_ZEROES)
++              *result = __send_write_zeroes(ci, ti);
++      else
++              return false;
++
++      return true;
++}
++
+ /*
+  * Select the correct strategy for processing a non-flush bio.
+  */
+@@ -1491,12 +1508,8 @@ static int __split_and_process_non_flush
+       if (!dm_target_is_valid(ti))
+               return -EIO;
+-      if (unlikely(bio_op(bio) == REQ_OP_DISCARD))
+-              return __send_discard(ci, ti);
+-      else if (unlikely(bio_op(bio) == REQ_OP_WRITE_SAME))
+-              return __send_write_same(ci, ti);
+-      else if (unlikely(bio_op(bio) == REQ_OP_WRITE_ZEROES))
+-              return __send_write_zeroes(ci, ti);
++      if (unlikely(__process_abnormal_io(ci, ti, &r)))
++              return r;
+       if (bio_op(bio) == REQ_OP_ZONE_REPORT)
+               len = ci->sector_count;
+@@ -1617,9 +1630,12 @@ static blk_qc_t __process_bio(struct map
+                       goto out;
+               }
+-              tio = alloc_tio(&ci, ti, 0, GFP_NOIO);
+               ci.bio = bio;
+               ci.sector_count = bio_sectors(bio);
++              if (unlikely(__process_abnormal_io(&ci, ti, &error)))
++                      goto out;
++
++              tio = alloc_tio(&ci, ti, 0, GFP_NOIO);
+               ret = __clone_and_map_simple_bio(&ci, tio, NULL);
+       }
+ out:
diff --git a/queue-4.16/dm-crypt-limit-the-number-of-allocated-pages.patch b/queue-4.16/dm-crypt-limit-the-number-of-allocated-pages.patch
new file mode 100644 (file)
index 0000000..d7ace67
--- /dev/null
@@ -0,0 +1,151 @@
+From 5059353df86e2573ccd9d43fd9d9396dcec47ca2 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Sun, 13 Aug 2017 22:45:08 -0400
+Subject: dm crypt: limit the number of allocated pages
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit 5059353df86e2573ccd9d43fd9d9396dcec47ca2 upstream.
+
+dm-crypt consumes an excessive amount memory when the user attempts to
+zero a dm-crypt device with "blkdiscard -z". The command "blkdiscard -z"
+calls the BLKZEROOUT ioctl, it goes to the function __blkdev_issue_zeroout,
+__blkdev_issue_zeroout sends a large amount of write bios that contain
+the zero page as their payload.
+
+For each incoming page, dm-crypt allocates another page that holds the
+encrypted data, so when processing "blkdiscard -z", dm-crypt tries to
+allocate the amount of memory that is equal to the size of the device.
+This can trigger OOM killer or cause system crash.
+
+Fix this by limiting the amount of memory that dm-crypt allocates to 2%
+of total system memory. This limit is system-wide and is divided by the
+number of active dm-crypt devices and each device receives an equal
+share.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/dm-crypt.c |   66 +++++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 65 insertions(+), 1 deletion(-)
+
+--- a/drivers/md/dm-crypt.c
++++ b/drivers/md/dm-crypt.c
+@@ -148,6 +148,8 @@ struct crypt_config {
+       mempool_t *tag_pool;
+       unsigned tag_pool_max_sectors;
++      struct percpu_counter n_allocated_pages;
++
+       struct bio_set *bs;
+       struct mutex bio_alloc_lock;
+@@ -219,6 +221,12 @@ struct crypt_config {
+ #define MAX_TAG_SIZE  480
+ #define POOL_ENTRY_SIZE       512
++static DEFINE_SPINLOCK(dm_crypt_clients_lock);
++static unsigned dm_crypt_clients_n = 0;
++static volatile unsigned long dm_crypt_pages_per_client;
++#define DM_CRYPT_MEMORY_PERCENT                       2
++#define DM_CRYPT_MIN_PAGES_PER_CLIENT         (BIO_MAX_PAGES * 16)
++
+ static void clone_init(struct dm_crypt_io *, struct bio *);
+ static void kcryptd_queue_crypt(struct dm_crypt_io *io);
+ static struct scatterlist *crypt_get_sg_data(struct crypt_config *cc,
+@@ -2155,6 +2163,43 @@ static int crypt_wipe_key(struct crypt_c
+       return r;
+ }
++static void crypt_calculate_pages_per_client(void)
++{
++      unsigned long pages = (totalram_pages - totalhigh_pages) * DM_CRYPT_MEMORY_PERCENT / 100;
++
++      if (!dm_crypt_clients_n)
++              return;
++
++      pages /= dm_crypt_clients_n;
++      if (pages < DM_CRYPT_MIN_PAGES_PER_CLIENT)
++              pages = DM_CRYPT_MIN_PAGES_PER_CLIENT;
++      dm_crypt_pages_per_client = pages;
++}
++
++static void *crypt_page_alloc(gfp_t gfp_mask, void *pool_data)
++{
++      struct crypt_config *cc = pool_data;
++      struct page *page;
++
++      if (unlikely(percpu_counter_compare(&cc->n_allocated_pages, dm_crypt_pages_per_client) >= 0) &&
++          likely(gfp_mask & __GFP_NORETRY))
++              return NULL;
++
++      page = alloc_page(gfp_mask);
++      if (likely(page != NULL))
++              percpu_counter_add(&cc->n_allocated_pages, 1);
++
++      return page;
++}
++
++static void crypt_page_free(void *page, void *pool_data)
++{
++      struct crypt_config *cc = pool_data;
++
++      __free_page(page);
++      percpu_counter_sub(&cc->n_allocated_pages, 1);
++}
++
+ static void crypt_dtr(struct dm_target *ti)
+ {
+       struct crypt_config *cc = ti->private;
+@@ -2181,6 +2226,10 @@ static void crypt_dtr(struct dm_target *
+       mempool_destroy(cc->req_pool);
+       mempool_destroy(cc->tag_pool);
++      if (cc->page_pool)
++              WARN_ON(percpu_counter_sum(&cc->n_allocated_pages) != 0);
++      percpu_counter_destroy(&cc->n_allocated_pages);
++
+       if (cc->iv_gen_ops && cc->iv_gen_ops->dtr)
+               cc->iv_gen_ops->dtr(cc);
+@@ -2197,6 +2246,12 @@ static void crypt_dtr(struct dm_target *
+       /* Must zero key material before freeing */
+       kzfree(cc);
++
++      spin_lock(&dm_crypt_clients_lock);
++      WARN_ON(!dm_crypt_clients_n);
++      dm_crypt_clients_n--;
++      crypt_calculate_pages_per_client();
++      spin_unlock(&dm_crypt_clients_lock);
+ }
+ static int crypt_ctr_ivmode(struct dm_target *ti, const char *ivmode)
+@@ -2644,6 +2699,15 @@ static int crypt_ctr(struct dm_target *t
+       ti->private = cc;
++      spin_lock(&dm_crypt_clients_lock);
++      dm_crypt_clients_n++;
++      crypt_calculate_pages_per_client();
++      spin_unlock(&dm_crypt_clients_lock);
++
++      ret = percpu_counter_init(&cc->n_allocated_pages, 0, GFP_KERNEL);
++      if (ret < 0)
++              goto bad;
++
+       /* Optional parameters need to be read before cipher constructor */
+       if (argc > 5) {
+               ret = crypt_ctr_optional(ti, argc - 5, &argv[5]);
+@@ -2698,7 +2762,7 @@ static int crypt_ctr(struct dm_target *t
+               ALIGN(sizeof(struct dm_crypt_io) + cc->dmreq_start + additional_req_size,
+                     ARCH_KMALLOC_MINALIGN);
+-      cc->page_pool = mempool_create_page_pool(BIO_MAX_PAGES, 0);
++      cc->page_pool = mempool_create(BIO_MAX_PAGES, crypt_page_alloc, crypt_page_free, cc);
+       if (!cc->page_pool) {
+               ti->error = "Cannot allocate page mempool";
+               goto bad;
diff --git a/queue-4.16/dm-raid-fix-nosync-status.patch b/queue-4.16/dm-raid-fix-nosync-status.patch
new file mode 100644 (file)
index 0000000..d17574e
--- /dev/null
@@ -0,0 +1,35 @@
+From 880bcce0dcc3172fe865352b492c41d85290cb8d Mon Sep 17 00:00:00 2001
+From: Heinz Mauelshagen <heinzm@redhat.com>
+Date: Fri, 16 Mar 2018 23:01:59 +0100
+Subject: dm raid: fix nosync status
+
+From: Heinz Mauelshagen <heinzm@redhat.com>
+
+commit 880bcce0dcc3172fe865352b492c41d85290cb8d upstream.
+
+Fix a race for "nosync" activations providing "aa.." device health
+characters and "0/N" sync ratio rather than "AA..." and "N/N".  Occurs
+when status for the raid set is retrieved during resume before the MD
+sync thread starts and clears the MD_RECOVERY_NEEDED flag.
+
+Cc: stable@vger.kernel.org # 4.16+
+Signed-off-by: Heinz Mauelshagen <heinzm@redhat.com>
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/dm-raid.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/md/dm-raid.c
++++ b/drivers/md/dm-raid.c
+@@ -3408,7 +3408,8 @@ static sector_t rs_get_progress(struct r
+               set_bit(RT_FLAG_RS_IN_SYNC, &rs->runtime_flags);
+       } else {
+-              if (!test_bit(MD_RECOVERY_INTR, &recovery) &&
++              if (!test_bit(__CTR_FLAG_NOSYNC, &rs->ctr_flags) &&
++                  !test_bit(MD_RECOVERY_INTR, &recovery) &&
+                   (test_bit(MD_RECOVERY_NEEDED, &recovery) ||
+                    test_bit(MD_RECOVERY_RESHAPE, &recovery) ||
+                    test_bit(MD_RECOVERY_RUNNING, &recovery)))
diff --git a/queue-4.16/dmaengine-at_xdmac-fix-rare-residue-corruption.patch b/queue-4.16/dmaengine-at_xdmac-fix-rare-residue-corruption.patch
new file mode 100644 (file)
index 0000000..ad4f608
--- /dev/null
@@ -0,0 +1,71 @@
+From c5637476bbf9bb86c7f0413b8f4822a73d8d2d07 Mon Sep 17 00:00:00 2001
+From: Maxime Jayat <maxime.jayat@mobile-devices.fr>
+Date: Thu, 22 Feb 2018 12:39:55 +0100
+Subject: dmaengine: at_xdmac: fix rare residue corruption
+
+From: Maxime Jayat <maxime.jayat@mobile-devices.fr>
+
+commit c5637476bbf9bb86c7f0413b8f4822a73d8d2d07 upstream.
+
+Despite the efforts made to correctly read the NDA and CUBC registers,
+the order in which the registers are read could sometimes lead to an
+inconsistent state.
+
+Re-using the timeline from the comments, this following timing of
+registers reads could lead to reading NDA with value "@desc2" and
+CUBC with value "MAX desc1":
+
+ INITD --------                    ------------
+              |____________________|
+       _______________________  _______________
+ NDA       @desc2             \/   @desc3
+       _______________________/\_______________
+       __________  ___________  _______________
+ CUBC       0    \/ MAX desc1 \/  MAX desc2
+       __________/\___________/\_______________
+        |  |          |  |
+Events:(1)(2)        (3)(4)
+
+(1) check_nda = @desc2
+(2) initd = 1
+(3) cur_ubc = MAX desc1
+(4) cur_nda = @desc2
+
+This is allowed by the condition ((check_nda == cur_nda) && initd),
+despite cur_ubc and cur_nda being in the precise state we don't want.
+
+This error leads to incorrect residue computation.
+
+Fix it by inversing the order in which CUBC and INITD are read. This
+makes sure that NDA and CUBC are always read together either _before_
+INITD goes to 0 or _after_ it is back at 1.
+The case where NDA is read before INITD is at 0 and CUBC is read after
+INITD is back at 1 will be rejected by check_nda and cur_nda being
+different.
+
+Fixes: 53398f488821 ("dmaengine: at_xdmac: fix residue corruption")
+Cc: stable@vger.kernel.org
+Signed-off-by: Maxime Jayat <maxime.jayat@mobile-devices.fr>
+Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
+Signed-off-by: Vinod Koul <vinod.koul@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/dma/at_xdmac.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/dma/at_xdmac.c
++++ b/drivers/dma/at_xdmac.c
+@@ -1471,10 +1471,10 @@ at_xdmac_tx_status(struct dma_chan *chan
+       for (retry = 0; retry < AT_XDMAC_RESIDUE_MAX_RETRIES; retry++) {
+               check_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
+               rmb();
+-              initd = !!(at_xdmac_chan_read(atchan, AT_XDMAC_CC) & AT_XDMAC_CC_INITD);
+-              rmb();
+               cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC);
+               rmb();
++              initd = !!(at_xdmac_chan_read(atchan, AT_XDMAC_CC) & AT_XDMAC_CC_INITD);
++              rmb();
+               cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
+               rmb();
diff --git a/queue-4.16/drivers-infiniband-core-verbs.c-fix-build-with-gcc-4.4.4.patch b/queue-4.16/drivers-infiniband-core-verbs.c-fix-build-with-gcc-4.4.4.patch
new file mode 100644 (file)
index 0000000..0d1be87
--- /dev/null
@@ -0,0 +1,44 @@
+From 6ee687735e745eafae9e6b93d1ea70bc52e7ad07 Mon Sep 17 00:00:00 2001
+From: Andrew Morton <akpm@linux-foundation.org>
+Date: Tue, 13 Mar 2018 14:51:57 -0700
+Subject: drivers/infiniband/core/verbs.c: fix build with gcc-4.4.4
+
+From: Andrew Morton <akpm@linux-foundation.org>
+
+commit 6ee687735e745eafae9e6b93d1ea70bc52e7ad07 upstream.
+
+gcc-4.4.4 has issues with initialization of anonymous unions.
+
+drivers/infiniband/core/verbs.c: In function '__ib_drain_sq':
+drivers/infiniband/core/verbs.c:2204: error: unknown field 'wr_cqe' specified in initializer
+drivers/infiniband/core/verbs.c:2204: warning: initialization makes integer from pointer without a cast
+
+Work around this.
+
+Fixes: a1ae7d0345edd5 ("RDMA/core: Avoid that ib_drain_qp() triggers an out-of-bounds stack access")
+Cc: Bart Van Assche <bart.vanassche@wdc.com>
+Cc: Steve Wise <swise@opengridcomputing.com>
+Cc: Sagi Grimberg <sagi@grimberg.me>
+Cc: Jason Gunthorpe <jgg@mellanox.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/core/verbs.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/infiniband/core/verbs.c
++++ b/drivers/infiniband/core/verbs.c
+@@ -2197,8 +2197,9 @@ static void __ib_drain_sq(struct ib_qp *
+       struct ib_send_wr *bad_swr;
+       struct ib_rdma_wr swr = {
+               .wr = {
++                      .next = NULL,
++                      { .wr_cqe       = &sdrain.cqe, },
+                       .opcode = IB_WR_RDMA_WRITE,
+-                      .wr_cqe = &sdrain.cqe,
+               },
+       };
+       int ret;
diff --git a/queue-4.16/drivers-infiniband-ulp-srpt-ib_srpt.c-fix-build-with-gcc-4.4.4.patch b/queue-4.16/drivers-infiniband-ulp-srpt-ib_srpt.c-fix-build-with-gcc-4.4.4.patch
new file mode 100644 (file)
index 0000000..0a647e6
--- /dev/null
@@ -0,0 +1,43 @@
+From 06892cc190550807d332c95a0114c7e175584012 Mon Sep 17 00:00:00 2001
+From: Andrew Morton <akpm@linux-foundation.org>
+Date: Tue, 13 Mar 2018 15:06:45 -0700
+Subject: drivers/infiniband/ulp/srpt/ib_srpt.c: fix build with gcc-4.4.4
+
+From: Andrew Morton <akpm@linux-foundation.org>
+
+commit 06892cc190550807d332c95a0114c7e175584012 upstream.
+
+gcc-4.4.4 has issues with initialization of anonymous unions:
+
+drivers/infiniband/ulp/srpt/ib_srpt.c: In function 'srpt_zerolength_write':
+drivers/infiniband/ulp/srpt/ib_srpt.c:854: error: unknown field 'wr_cqe' specified in initializer
+drivers/infiniband/ulp/srpt/ib_srpt.c:854: warning: initialization makes integer from pointer without a cast
+
+Work aound this.
+
+Fixes: 2a78cb4db487 ("IB/srpt: Fix an out-of-bounds stack access in srpt_zerolength_write()")
+Cc: Bart Van Assche <bart.vanassche@wdc.com>
+Cc: Christoph Hellwig <hch@lst.de>
+Cc: Jason Gunthorpe <jgg@mellanox.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/ulp/srpt/ib_srpt.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
++++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
+@@ -841,8 +841,9 @@ static int srpt_zerolength_write(struct
+       struct ib_send_wr *bad_wr;
+       struct ib_rdma_wr wr = {
+               .wr = {
++                      .next           = NULL,
++                      { .wr_cqe       = &ch->zw_cqe, },
+                       .opcode         = IB_WR_RDMA_WRITE,
+-                      .wr_cqe         = &ch->zw_cqe,
+                       .send_flags     = IB_SEND_SIGNALED,
+               }
+       };
diff --git a/queue-4.16/ib-srp-fix-completion-vector-assignment-algorithm.patch b/queue-4.16/ib-srp-fix-completion-vector-assignment-algorithm.patch
new file mode 100644 (file)
index 0000000..0b9ca8e
--- /dev/null
@@ -0,0 +1,49 @@
+From 3a148896b24adf8688dc0c59af54531931677a40 Mon Sep 17 00:00:00 2001
+From: Bart Van Assche <bart.vanassche@wdc.com>
+Date: Mon, 12 Feb 2018 09:50:25 -0800
+Subject: IB/srp: Fix completion vector assignment algorithm
+
+From: Bart Van Assche <bart.vanassche@wdc.com>
+
+commit 3a148896b24adf8688dc0c59af54531931677a40 upstream.
+
+Ensure that cv_end is equal to ibdev->num_comp_vectors for the
+NUMA node with the highest index. This patch improves spreading
+of RDMA channels over completion vectors and thereby improves
+performance, especially on systems with only a single NUMA node.
+This patch drops support for the comp_vector login parameter by
+ignoring the value of that parameter since I have not found a
+good way to combine support for that parameter and automatic
+spreading of RDMA channels over completion vectors.
+
+Fixes: d92c0da71a35 ("IB/srp: Add multichannel support")
+Reported-by: Alexander Schmid <alex@modula-shop-systems.de>
+Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com>
+Cc: Alexander Schmid <alex@modula-shop-systems.de>
+Cc: stable@vger.kernel.org
+Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/ulp/srp/ib_srp.c |   10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+--- a/drivers/infiniband/ulp/srp/ib_srp.c
++++ b/drivers/infiniband/ulp/srp/ib_srp.c
+@@ -3873,12 +3873,10 @@ static ssize_t srp_create_target(struct
+                                     num_online_nodes());
+               const int ch_end = ((node_idx + 1) * target->ch_count /
+                                   num_online_nodes());
+-              const int cv_start = (node_idx * ibdev->num_comp_vectors /
+-                                    num_online_nodes() + target->comp_vector)
+-                                   % ibdev->num_comp_vectors;
+-              const int cv_end = ((node_idx + 1) * ibdev->num_comp_vectors /
+-                                  num_online_nodes() + target->comp_vector)
+-                                 % ibdev->num_comp_vectors;
++              const int cv_start = node_idx * ibdev->num_comp_vectors /
++                                   num_online_nodes();
++              const int cv_end = (node_idx + 1) * ibdev->num_comp_vectors /
++                                 num_online_nodes();
+               int cpu_idx = 0;
+               for_each_online_cpu(cpu) {
diff --git a/queue-4.16/ib-srp-fix-srp_abort.patch b/queue-4.16/ib-srp-fix-srp_abort.patch
new file mode 100644 (file)
index 0000000..03fdf2d
--- /dev/null
@@ -0,0 +1,41 @@
+From e68088e78d82920632eba112b968e49d588d02a2 Mon Sep 17 00:00:00 2001
+From: Bart Van Assche <bart.vanassche@wdc.com>
+Date: Fri, 23 Feb 2018 14:09:24 -0800
+Subject: IB/srp: Fix srp_abort()
+
+From: Bart Van Assche <bart.vanassche@wdc.com>
+
+commit e68088e78d82920632eba112b968e49d588d02a2 upstream.
+
+Before commit e494f6a72839 ("[SCSI] improved eh timeout handler") it
+did not really matter whether or not abort handlers like srp_abort()
+called .scsi_done() when returning another value than SUCCESS. Since
+that commit however this matters. Hence only call .scsi_done() when
+returning SUCCESS.
+
+Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/ulp/srp/ib_srp.c |    8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/infiniband/ulp/srp/ib_srp.c
++++ b/drivers/infiniband/ulp/srp/ib_srp.c
+@@ -2974,9 +2974,11 @@ static int srp_abort(struct scsi_cmnd *s
+               ret = FAST_IO_FAIL;
+       else
+               ret = FAILED;
+-      srp_free_req(ch, req, scmnd, 0);
+-      scmnd->result = DID_ABORT << 16;
+-      scmnd->scsi_done(scmnd);
++      if (ret == SUCCESS) {
++              srp_free_req(ch, req, scmnd, 0);
++              scmnd->result = DID_ABORT << 16;
++              scmnd->scsi_done(scmnd);
++      }
+       return ret;
+ }
diff --git a/queue-4.16/ib-srpt-fix-an-out-of-bounds-stack-access-in-srpt_zerolength_write.patch b/queue-4.16/ib-srpt-fix-an-out-of-bounds-stack-access-in-srpt_zerolength_write.patch
new file mode 100644 (file)
index 0000000..e6f3ff3
--- /dev/null
@@ -0,0 +1,74 @@
+From 2a78cb4db487372152bed2055c038f9634d595e8 Mon Sep 17 00:00:00 2001
+From: Bart Van Assche <bart.vanassche@wdc.com>
+Date: Thu, 1 Mar 2018 14:00:30 -0800
+Subject: IB/srpt: Fix an out-of-bounds stack access in srpt_zerolength_write()
+
+From: Bart Van Assche <bart.vanassche@wdc.com>
+
+commit 2a78cb4db487372152bed2055c038f9634d595e8 upstream.
+
+Avoid triggering an out-of-bounds stack access by changing the type
+of 'wr' from ib_send_wr into ib_rdma_wr.
+
+This patch fixes the following KASAN bug report:
+
+BUG: KASAN: stack-out-of-bounds in rxe_post_send+0x7a9/0x9a0 [rdma_rxe]
+Read of size 8 at addr ffff880068197a48 by task kworker/2:1/44
+
+Workqueue: ib_cm cm_work_handler [ib_cm]
+Call Trace:
+ dump_stack+0x8e/0xcd
+ print_address_description+0x6f/0x280
+ kasan_report+0x25a/0x380
+ __asan_load8+0x54/0x90
+ rxe_post_send+0x7a9/0x9a0 [rdma_rxe]
+ srpt_zerolength_write+0xf0/0x180 [ib_srpt]
+ srpt_cm_rtu_recv+0x68/0x110 [ib_srpt]
+ srpt_rdma_cm_handler+0xbb/0x15b [ib_srpt]
+ cma_ib_handler+0x1aa/0x4a0 [rdma_cm]
+ cm_process_work+0x30/0x100 [ib_cm]
+ cm_work_handler+0xa86/0x351b [ib_cm]
+ process_one_work+0x475/0x9f0
+ worker_thread+0x69/0x690
+ kthread+0x1ad/0x1d0
+ ret_from_fork+0x3a/0x50
+
+Fixes: aaf45bd83eba ("IB/srpt: Detect session shutdown reliably")
+Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com>
+Cc: Christoph Hellwig <hch@lst.de>
+Cc: stable@vger.kernel.org
+Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/ulp/srpt/ib_srpt.c |   15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
++++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
+@@ -838,16 +838,19 @@ static int srpt_post_recv(struct srpt_de
+  */
+ static int srpt_zerolength_write(struct srpt_rdma_ch *ch)
+ {
+-      struct ib_send_wr wr, *bad_wr;
++      struct ib_send_wr *bad_wr;
++      struct ib_rdma_wr wr = {
++              .wr = {
++                      .opcode         = IB_WR_RDMA_WRITE,
++                      .wr_cqe         = &ch->zw_cqe,
++                      .send_flags     = IB_SEND_SIGNALED,
++              }
++      };
+       pr_debug("%s-%d: queued zerolength write\n", ch->sess_name,
+                ch->qp->qp_num);
+-      memset(&wr, 0, sizeof(wr));
+-      wr.opcode = IB_WR_RDMA_WRITE;
+-      wr.wr_cqe = &ch->zw_cqe;
+-      wr.send_flags = IB_SEND_SIGNALED;
+-      return ib_post_send(ch->qp, &wr, &bad_wr);
++      return ib_post_send(ch->qp, &wr.wr, &bad_wr);
+ }
+ static void srpt_zerolength_write_done(struct ib_cq *cq, struct ib_wc *wc)
diff --git a/queue-4.16/libnvdimm-dimm-fix-dpa-reservation-vs-uninitialized-label-area.patch b/queue-4.16/libnvdimm-dimm-fix-dpa-reservation-vs-uninitialized-label-area.patch
new file mode 100644 (file)
index 0000000..73cd2a8
--- /dev/null
@@ -0,0 +1,51 @@
+From c31898c8c711f2bbbcaebe802a55827e288d875a Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Fri, 6 Apr 2018 11:25:38 -0700
+Subject: libnvdimm, dimm: fix dpa reservation vs uninitialized label area
+
+From: Dan Williams <dan.j.williams@intel.com>
+
+commit c31898c8c711f2bbbcaebe802a55827e288d875a upstream.
+
+At initialization time the 'dimm' driver caches a copy of the memory
+device's label area and reserves address space for each of the
+namespaces defined.
+
+However, as can be seen below, the reservation occurs even when the
+index blocks are invalid:
+
+ nvdimm nmem0: nvdimm_init_config_data: len: 131072 rc: 0
+ nvdimm nmem0: config data size: 131072
+ nvdimm nmem0: __nd_label_validate: nsindex0 labelsize 1 invalid
+ nvdimm nmem0: __nd_label_validate: nsindex1 labelsize 1 invalid
+ nvdimm nmem0: : pmem-6025e505: 0x1000000000 @ 0xf50000000 reserve <-- bad
+
+Gate dpa reservation on the presence of valid index blocks.
+
+Cc: <stable@vger.kernel.org>
+Fixes: 4a826c83db4e ("libnvdimm: namespace indices: read and validate")
+Reported-by: Krzysztof Rusocki <krzysztof.rusocki@intel.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/nvdimm/dimm.c |    8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/nvdimm/dimm.c
++++ b/drivers/nvdimm/dimm.c
+@@ -67,9 +67,11 @@ static int nvdimm_probe(struct device *d
+       ndd->ns_next = nd_label_next_nsindex(ndd->ns_current);
+       nd_label_copy(ndd, to_next_namespace_index(ndd),
+                       to_current_namespace_index(ndd));
+-      rc = nd_label_reserve_dpa(ndd);
+-      if (ndd->ns_current >= 0)
+-              nvdimm_set_aliasing(dev);
++      if (ndd->ns_current >= 0) {
++              rc = nd_label_reserve_dpa(ndd);
++              if (rc == 0)
++                      nvdimm_set_aliasing(dev);
++      }
+       nvdimm_clear_locked(dev);
+       nvdimm_bus_unlock(dev);
diff --git a/queue-4.16/libnvdimm-namespace-use-a-safe-lookup-for-dimm-device-name.patch b/queue-4.16/libnvdimm-namespace-use-a-safe-lookup-for-dimm-device-name.patch
new file mode 100644 (file)
index 0000000..f6e5758
--- /dev/null
@@ -0,0 +1,70 @@
+From 4f8672201b7e7ed4f5f6c3cf6dcd080648580582 Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Fri, 6 Apr 2018 16:37:21 -0700
+Subject: libnvdimm, namespace: use a safe lookup for dimm device name
+
+From: Dan Williams <dan.j.williams@intel.com>
+
+commit 4f8672201b7e7ed4f5f6c3cf6dcd080648580582 upstream.
+
+The following NULL dereference results from incorrectly assuming that
+ndd is valid in this print:
+
+  struct nvdimm_drvdata *ndd = to_ndd(&nd_region->mapping[i]);
+
+  /*
+   * Give up if we don't find an instance of a uuid at each
+   * position (from 0 to nd_region->ndr_mappings - 1), or if we
+   * find a dimm with two instances of the same uuid.
+   */
+  dev_err(&nd_region->dev, "%s missing label for %pUb\n",
+                  dev_name(ndd->dev), nd_label->uuid);
+
+ BUG: unable to handle kernel NULL pointer dereference at 0000000000000000
+ IP: nd_region_register_namespaces+0xd67/0x13c0 [libnvdimm]
+ PGD 0 P4D 0
+ Oops: 0000 [#1] SMP PTI
+ CPU: 43 PID: 673 Comm: kworker/u609:10 Not tainted 4.16.0-rc4+ #1
+ [..]
+ RIP: 0010:nd_region_register_namespaces+0xd67/0x13c0 [libnvdimm]
+ [..]
+ Call Trace:
+  ? devres_add+0x2f/0x40
+  ? devm_kmalloc+0x52/0x60
+  ? nd_region_activate+0x9c/0x320 [libnvdimm]
+  nd_region_probe+0x94/0x260 [libnvdimm]
+  ? kernfs_add_one+0xe4/0x130
+  nvdimm_bus_probe+0x63/0x100 [libnvdimm]
+
+Switch to using the nvdimm device directly.
+
+Fixes: 0e3b0d123c8f ("libnvdimm, namespace: allow multiple pmem...")
+Cc: <stable@vger.kernel.org>
+Reported-by: Dave Jiang <dave.jiang@intel.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/nvdimm/namespace_devs.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/nvdimm/namespace_devs.c
++++ b/drivers/nvdimm/namespace_devs.c
+@@ -1926,7 +1926,7 @@ static struct device *create_namespace_p
+       }
+       if (i < nd_region->ndr_mappings) {
+-              struct nvdimm_drvdata *ndd = to_ndd(&nd_region->mapping[i]);
++              struct nvdimm *nvdimm = nd_region->mapping[i].nvdimm;
+               /*
+                * Give up if we don't find an instance of a uuid at each
+@@ -1934,7 +1934,7 @@ static struct device *create_namespace_p
+                * find a dimm with two instances of the same uuid.
+                */
+               dev_err(&nd_region->dev, "%s missing label for %pUb\n",
+-                              dev_name(ndd->dev), nd_label->uuid);
++                              nvdimm_name(nvdimm), nd_label->uuid);
+               rc = -EINVAL;
+               goto err;
+       }
diff --git a/queue-4.16/rdma-core-avoid-that-ib_drain_qp-triggers-an-out-of-bounds-stack-access.patch b/queue-4.16/rdma-core-avoid-that-ib_drain_qp-triggers-an-out-of-bounds-stack-access.patch
new file mode 100644 (file)
index 0000000..7dd7197
--- /dev/null
@@ -0,0 +1,92 @@
+From a1ae7d0345edd593d6725d3218434d903a0af95d Mon Sep 17 00:00:00 2001
+From: Bart Van Assche <bart.vanassche@wdc.com>
+Date: Thu, 1 Mar 2018 14:00:28 -0800
+Subject: RDMA/core: Avoid that ib_drain_qp() triggers an out-of-bounds stack access
+
+From: Bart Van Assche <bart.vanassche@wdc.com>
+
+commit a1ae7d0345edd593d6725d3218434d903a0af95d upstream.
+
+This patch fixes the following KASAN complaint:
+
+==================================================================
+BUG: KASAN: stack-out-of-bounds in rxe_post_send+0x77d/0x9b0 [rdma_rxe]
+Read of size 8 at addr ffff880061aef860 by task 01/1080
+
+CPU: 2 PID: 1080 Comm: 01 Not tainted 4.16.0-rc3-dbg+ #2
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.0.0-prebuilt.qemu-project.org 04/01/2014
+Call Trace:
+dump_stack+0x85/0xc7
+print_address_description+0x65/0x270
+kasan_report+0x231/0x350
+rxe_post_send+0x77d/0x9b0 [rdma_rxe]
+__ib_drain_sq+0x1ad/0x250 [ib_core]
+ib_drain_qp+0x9/0x30 [ib_core]
+srp_destroy_qp+0x51/0x70 [ib_srp]
+srp_free_ch_ib+0xfc/0x380 [ib_srp]
+srp_create_target+0x1071/0x19e0 [ib_srp]
+kernfs_fop_write+0x180/0x210
+__vfs_write+0xb1/0x2e0
+vfs_write+0xf6/0x250
+SyS_write+0x99/0x110
+do_syscall_64+0xee/0x2b0
+entry_SYSCALL_64_after_hwframe+0x42/0xb7
+
+The buggy address belongs to the page:
+page:ffffea000186bbc0 count:0 mapcount:0 mapping:0000000000000000 index:0x0
+flags: 0x4000000000000000()
+raw: 4000000000000000 0000000000000000 0000000000000000 00000000ffffffff
+raw: 0000000000000000 ffffea000186bbe0 0000000000000000 0000000000000000
+page dumped because: kasan: bad access detected
+
+Memory state around the buggy address:
+ffff880061aef700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ffff880061aef780: 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00
+>ffff880061aef800: f2 f2 f2 f2 f2 f2 f2 00 00 00 00 00 f2 f2 f2 f2
+                                                      ^
+ffff880061aef880: f2 f2 f2 00 00 00 00 00 00 00 00 00 00 00 f2 f2
+ffff880061aef900: f2 f2 f2 00 00 00 00 00 00 00 00 00 00 00 00 00
+==================================================================
+
+Fixes: 765d67748bcf ("IB: new common API for draining queues")
+Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com>
+Cc: Steve Wise <swise@opengridcomputing.com>
+Cc: Sagi Grimberg <sagi@grimberg.me>
+Cc: stable@vger.kernel.org
+Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/core/verbs.c |   11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+--- a/drivers/infiniband/core/verbs.c
++++ b/drivers/infiniband/core/verbs.c
+@@ -2194,7 +2194,13 @@ static void __ib_drain_sq(struct ib_qp *
+       struct ib_cq *cq = qp->send_cq;
+       struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
+       struct ib_drain_cqe sdrain;
+-      struct ib_send_wr swr = {}, *bad_swr;
++      struct ib_send_wr *bad_swr;
++      struct ib_rdma_wr swr = {
++              .wr = {
++                      .opcode = IB_WR_RDMA_WRITE,
++                      .wr_cqe = &sdrain.cqe,
++              },
++      };
+       int ret;
+       ret = ib_modify_qp(qp, &attr, IB_QP_STATE);
+@@ -2203,11 +2209,10 @@ static void __ib_drain_sq(struct ib_qp *
+               return;
+       }
+-      swr.wr_cqe = &sdrain.cqe;
+       sdrain.cqe.done = ib_drain_qp_done;
+       init_completion(&sdrain.done);
+-      ret = ib_post_send(qp, &swr, &bad_swr);
++      ret = ib_post_send(qp, &swr.wr, &bad_swr);
+       if (ret) {
+               WARN_ONCE(ret, "failed to drain send queue: %d\n", ret);
+               return;
diff --git a/queue-4.16/rdma-mlx5-protect-from-null-pointer-derefence.patch b/queue-4.16/rdma-mlx5-protect-from-null-pointer-derefence.patch
new file mode 100644 (file)
index 0000000..314e28d
--- /dev/null
@@ -0,0 +1,35 @@
+From 4289861d88d6c7b5e4c8cc7fe2ad6cdf0cdfc366 Mon Sep 17 00:00:00 2001
+From: Leon Romanovsky <leonro@mellanox.com>
+Date: Tue, 13 Mar 2018 15:29:24 +0200
+Subject: RDMA/mlx5: Protect from NULL pointer derefence
+
+From: Leon Romanovsky <leonro@mellanox.com>
+
+commit 4289861d88d6c7b5e4c8cc7fe2ad6cdf0cdfc366 upstream.
+
+The mlx5_ib_alloc_implicit_mr() can fail to acquire pages
+and the returned mr pointer won't be valid. Ensure that it
+is not error prior to access.
+
+Cc: <stable@vger.kernel.org> # 4.10
+Fixes: 81713d3788d2 ("IB/mlx5: Add implicit MR support")
+Reported-by: Noa Osherovich <noaos@mellanox.com>
+Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/hw/mlx5/mr.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/infiniband/hw/mlx5/mr.c
++++ b/drivers/infiniband/hw/mlx5/mr.c
+@@ -1223,6 +1223,8 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct
+                       return ERR_PTR(-EINVAL);
+               mr = mlx5_ib_alloc_implicit_mr(to_mpd(pd), access_flags);
++              if (IS_ERR(mr))
++                      return ERR_CAST(mr);
+               return &mr->ibmr;
+       }
+ #endif
diff --git a/queue-4.16/rdma-rxe-fix-an-out-of-bounds-read.patch b/queue-4.16/rdma-rxe-fix-an-out-of-bounds-read.patch
new file mode 100644 (file)
index 0000000..2f2666f
--- /dev/null
@@ -0,0 +1,88 @@
+From a6544a624c3ff92a64e4aca3931fa064607bd3da Mon Sep 17 00:00:00 2001
+From: Bart Van Assche <bart.vanassche@wdc.com>
+Date: Thu, 1 Mar 2018 14:00:29 -0800
+Subject: RDMA/rxe: Fix an out-of-bounds read
+
+From: Bart Van Assche <bart.vanassche@wdc.com>
+
+commit a6544a624c3ff92a64e4aca3931fa064607bd3da upstream.
+
+This patch avoids that KASAN reports the following when the SRP initiator
+calls srp_post_send():
+
+==================================================================
+BUG: KASAN: stack-out-of-bounds in rxe_post_send+0x5c4/0x980 [rdma_rxe]
+Read of size 8 at addr ffff880066606e30 by task 02-mq/1074
+
+CPU: 2 PID: 1074 Comm: 02-mq Not tainted 4.16.0-rc3-dbg+ #1
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.0.0-prebuilt.qemu-project.org 04/01/2014
+Call Trace:
+dump_stack+0x85/0xc7
+print_address_description+0x65/0x270
+kasan_report+0x231/0x350
+rxe_post_send+0x5c4/0x980 [rdma_rxe]
+srp_post_send.isra.16+0x149/0x190 [ib_srp]
+srp_queuecommand+0x94d/0x1670 [ib_srp]
+scsi_dispatch_cmd+0x1c2/0x550 [scsi_mod]
+scsi_queue_rq+0x843/0xa70 [scsi_mod]
+blk_mq_dispatch_rq_list+0x143/0xac0
+blk_mq_do_dispatch_ctx+0x1c5/0x260
+blk_mq_sched_dispatch_requests+0x2bf/0x2f0
+__blk_mq_run_hw_queue+0xdb/0x160
+__blk_mq_delay_run_hw_queue+0xba/0x100
+blk_mq_run_hw_queue+0xf2/0x190
+blk_mq_sched_insert_request+0x163/0x2f0
+blk_execute_rq+0xb0/0x130
+scsi_execute+0x14e/0x260 [scsi_mod]
+scsi_probe_and_add_lun+0x366/0x13d0 [scsi_mod]
+__scsi_scan_target+0x18a/0x810 [scsi_mod]
+scsi_scan_target+0x11e/0x130 [scsi_mod]
+srp_create_target+0x1522/0x19e0 [ib_srp]
+kernfs_fop_write+0x180/0x210
+__vfs_write+0xb1/0x2e0
+vfs_write+0xf6/0x250
+SyS_write+0x99/0x110
+do_syscall_64+0xee/0x2b0
+entry_SYSCALL_64_after_hwframe+0x42/0xb7
+
+The buggy address belongs to the page:
+page:ffffea0001998180 count:0 mapcount:0 mapping:0000000000000000 index:0x0
+flags: 0x4000000000000000()
+raw: 4000000000000000 0000000000000000 0000000000000000 00000000ffffffff
+raw: dead000000000100 dead000000000200 0000000000000000 0000000000000000
+page dumped because: kasan: bad access detected
+
+Memory state around the buggy address:
+ffff880066606d00: 00 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1
+ffff880066606d80: f1 00 f2 f2 f2 f2 f2 f2 f2 00 00 f2 f2 f2 f2 f2
+>ffff880066606e00: f2 00 00 00 00 00 f2 f2 f2 f3 f3 f3 f3 00 00 00
+                                    ^
+ffff880066606e80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ffff880066606f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+==================================================================
+
+Fixes: 8700e3e7c485 ("Soft RoCE driver")
+Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com>
+Cc: Moni Shoua <monis@mellanox.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/sw/rxe/rxe_verbs.c |    5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+--- a/drivers/infiniband/sw/rxe/rxe_verbs.c
++++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
+@@ -711,9 +711,8 @@ static int init_send_wqe(struct rxe_qp *
+               memcpy(wqe->dma.sge, ibwr->sg_list,
+                      num_sge * sizeof(struct ib_sge));
+-      wqe->iova               = (mask & WR_ATOMIC_MASK) ?
+-                                      atomic_wr(ibwr)->remote_addr :
+-                                      rdma_wr(ibwr)->remote_addr;
++      wqe->iova = mask & WR_ATOMIC_MASK ? atomic_wr(ibwr)->remote_addr :
++              mask & WR_READ_OR_WRITE_MASK ? rdma_wr(ibwr)->remote_addr : 0;
+       wqe->mask               = mask;
+       wqe->dma.length         = length;
+       wqe->dma.resid          = length;
diff --git a/queue-4.16/rdma-ucma-don-t-allow-setting-rdma_option_ib_path-without-an-rdma-device.patch b/queue-4.16/rdma-ucma-don-t-allow-setting-rdma_option_ib_path-without-an-rdma-device.patch
new file mode 100644 (file)
index 0000000..16df36d
--- /dev/null
@@ -0,0 +1,35 @@
+From 8435168d50e66fa5eae01852769d20a36f9e5e83 Mon Sep 17 00:00:00 2001
+From: Roland Dreier <roland@purestorage.com>
+Date: Tue, 3 Apr 2018 15:33:01 -0700
+Subject: RDMA/ucma: Don't allow setting RDMA_OPTION_IB_PATH without an RDMA device
+
+From: Roland Dreier <roland@purestorage.com>
+
+commit 8435168d50e66fa5eae01852769d20a36f9e5e83 upstream.
+
+Check to make sure that ctx->cm_id->device is set before we use it.
+Otherwise userspace can trigger a NULL dereference by doing
+RDMA_USER_CM_CMD_SET_OPTION on an ID that is not bound to a device.
+
+Cc: <stable@vger.kernel.org>
+Reported-by: <syzbot+a67bc93e14682d92fc2f@syzkaller.appspotmail.com>
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/core/ucma.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/infiniband/core/ucma.c
++++ b/drivers/infiniband/core/ucma.c
+@@ -1241,6 +1241,9 @@ static int ucma_set_ib_path(struct ucma_
+       if (!optlen)
+               return -EINVAL;
++      if (!ctx->cm_id->device)
++              return -EINVAL;
++
+       memset(&sa_path, 0, sizeof(sa_path));
+       sa_path.rec_type = SA_PATH_REC_TYPE_IB;
index 8c6ec04844f68ceb0ef183bb1ce6a2649a7d0692..2a11eab1f681ede7b85ecf7ba5d7a23dccc4e3f1 100644 (file)
@@ -97,3 +97,28 @@ ext4-move-call-to-ext4_error-into-ext4_xattr_check_block.patch
 ext4-add-bounds-checking-to-ext4_xattr_find_entry.patch
 ext4-add-extra-checks-to-ext4_xattr_block_get.patch
 ext4-force-revalidation-of-directory-pointer-after-seekdir-2.patch
+dm-backfill-abnormal-io-support-to-non-splitting-io-submission.patch
+dm-crypt-limit-the-number-of-allocated-pages.patch
+rdma-ucma-don-t-allow-setting-rdma_option_ib_path-without-an-rdma-device.patch
+rdma-mlx5-protect-from-null-pointer-derefence.patch
+rdma-rxe-fix-an-out-of-bounds-read.patch
+rdma-core-avoid-that-ib_drain_qp-triggers-an-out-of-bounds-stack-access.patch
+xprtrdma-fix-latency-regression-on-numa-nfs-rdma-clients.patch
+xprtrdma-fix-corner-cases-when-handling-device-removal.patch
+alsa-pcm-avoid-potential-races-between-oss-ioctls-and-read-write.patch
+alsa-pcm-return-ebusy-for-oss-ioctls-changing-busy-streams.patch
+alsa-pcm-fix-mutex-unbalance-in-oss-emulation-ioctls.patch
+alsa-pcm-fix-uaf-at-pcm-release-via-pcm-timer-access.patch
+alsa-pcm-fix-endless-loop-for-xrun-recovery-in-oss-emulation.patch
+ib-srp-fix-srp_abort.patch
+ib-srp-fix-completion-vector-assignment-algorithm.patch
+ib-srpt-fix-an-out-of-bounds-stack-access-in-srpt_zerolength_write.patch
+drivers-infiniband-core-verbs.c-fix-build-with-gcc-4.4.4.patch
+drivers-infiniband-ulp-srpt-ib_srpt.c-fix-build-with-gcc-4.4.4.patch
+dm-raid-fix-nosync-status.patch
+dmaengine-at_xdmac-fix-rare-residue-corruption.patch
+cxl-fix-possible-deadlock-when-processing-page-faults-from-cxllib.patch
+tpm-self-test-failure-should-not-cause-suspend-to-fail.patch
+libnvdimm-dimm-fix-dpa-reservation-vs-uninitialized-label-area.patch
+libnvdimm-namespace-use-a-safe-lookup-for-dimm-device-name.patch
+vsprintf-do-not-preprocess-non-dereferenced-pointers-for-bprintf-px-and-pk.patch
diff --git a/queue-4.16/tpm-self-test-failure-should-not-cause-suspend-to-fail.patch b/queue-4.16/tpm-self-test-failure-should-not-cause-suspend-to-fail.patch
new file mode 100644 (file)
index 0000000..6ac53db
--- /dev/null
@@ -0,0 +1,60 @@
+From 0803d7befa15cab5717d667a97a66214d2a4c083 Mon Sep 17 00:00:00 2001
+From: Chris Chiu <chiu@endlessm.com>
+Date: Tue, 20 Mar 2018 15:36:40 +0800
+Subject: tpm: self test failure should not cause suspend to fail
+
+From: Chris Chiu <chiu@endlessm.com>
+
+commit 0803d7befa15cab5717d667a97a66214d2a4c083 upstream.
+
+The Acer Acer Veriton X4110G has a TPM device detected as:
+  tpm_tis 00:0b: 1.2 TPM (device-id 0xFE, rev-id 71)
+
+After the first S3 suspend, the following error appears during resume:
+  tpm tpm0: A TPM error(38) occurred continue selftest
+
+Any following S3 suspend attempts will now fail with this error:
+  tpm tpm0: Error (38) sending savestate before suspend
+  PM: Device 00:0b failed to suspend: error 38
+
+Error 38 is TPM_ERR_INVALID_POSTINIT which means the TPM is
+not in the correct state. This indicates that the platform BIOS
+is not sending the usual TPM_Startup command during S3 resume.
+>From this point onwards, all TPM commands will fail.
+
+The same issue was previously reported on Foxconn 6150BK8MC and
+Sony Vaio TX3.
+
+The platform behaviour seems broken here, but we should not break
+suspend/resume because of this.
+
+When the unexpected TPM state is encountered, set a flag to skip the
+affected TPM_SaveState command on later suspends.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Chris Chiu <chiu@endlessm.com>
+Signed-off-by: Daniel Drake <drake@endlessm.com>
+Link: http://lkml.kernel.org/r/CAB4CAwfSCvj1cudi+MWaB5g2Z67d9DwY1o475YOZD64ma23UiQ@mail.gmail.com
+Link: https://lkml.org/lkml/2011/3/28/192
+Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=591031
+Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/tpm-interface.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/char/tpm/tpm-interface.c
++++ b/drivers/char/tpm/tpm-interface.c
+@@ -969,6 +969,10 @@ int tpm_do_selftest(struct tpm_chip *chi
+       loops = jiffies_to_msecs(duration) / delay_msec;
+       rc = tpm_continue_selftest(chip);
++      if (rc == TPM_ERR_INVALID_POSTINIT) {
++              chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED;
++              dev_info(&chip->dev, "TPM not ready (%d)\n", rc);
++      }
+       /* This may fail if there was no TPM driver during a suspend/resume
+        * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST)
+        */
diff --git a/queue-4.16/vsprintf-do-not-preprocess-non-dereferenced-pointers-for-bprintf-px-and-pk.patch b/queue-4.16/vsprintf-do-not-preprocess-non-dereferenced-pointers-for-bprintf-px-and-pk.patch
new file mode 100644 (file)
index 0000000..4d12061
--- /dev/null
@@ -0,0 +1,45 @@
+From 1e6338cfb50e244c445ad7d891b35385bd0ee757 Mon Sep 17 00:00:00 2001
+From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>
+Date: Tue, 3 Apr 2018 14:38:53 -0400
+Subject: vsprintf: Do not preprocess non-dereferenced pointers for bprintf (%px and %pK)
+
+From: Steven Rostedt (VMware) <rostedt@goodmis.org>
+
+commit 1e6338cfb50e244c445ad7d891b35385bd0ee757 upstream.
+
+Commit 841a915d20c7b2 ("printf: Do not have bprintf dereference pointers")
+would preprocess various pointers that are dereferenced in the bprintf()
+because the recording and printing are done at two different times. Some
+pointers stayed dereferenced in the ring buffer because user space could
+handle them (namely "%pS" and friends). Pointers that are not dereferenced
+should not be processed immediately but instead just saved directly.
+
+Cc: stable@vger.kernel.org
+Fixes: 841a915d20c7b2 ("printf: Do not have bprintf dereference pointers")
+Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ lib/vsprintf.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/lib/vsprintf.c
++++ b/lib/vsprintf.c
+@@ -2591,6 +2591,8 @@ int vbin_printf(u32 *bin_buf, size_t siz
+                       case 's':
+                       case 'F':
+                       case 'f':
++                      case 'x':
++                      case 'K':
+                               save_arg(void *);
+                               break;
+                       default:
+@@ -2765,6 +2767,8 @@ int bstr_printf(char *buf, size_t size,
+                       case 's':
+                       case 'F':
+                       case 'f':
++                      case 'x':
++                      case 'K':
+                               process = true;
+                               break;
+                       default:
diff --git a/queue-4.16/xprtrdma-fix-corner-cases-when-handling-device-removal.patch b/queue-4.16/xprtrdma-fix-corner-cases-when-handling-device-removal.patch
new file mode 100644 (file)
index 0000000..5da541a
--- /dev/null
@@ -0,0 +1,83 @@
+From 25524288631fc5b7d33259fca1e0dc38146be5d6 Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Mon, 19 Mar 2018 14:23:16 -0400
+Subject: xprtrdma: Fix corner cases when handling device removal
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+commit 25524288631fc5b7d33259fca1e0dc38146be5d6 upstream.
+
+Michal Kalderon has found some corner cases around device unload
+with active NFS mounts that I didn't have the imagination to test
+when xprtrdma device removal was added last year.
+
+- The ULP device removal handler is responsible for deallocating
+  the PD. That wasn't clear to me initially, and my own testing
+  suggested it was not necessary, but that is incorrect.
+
+- The transport destruction path can no longer assume that there
+  is a valid ID.
+
+- When destroying a transport, ensure that ib_free_cq() is not
+  invoked on a CQ that was already released.
+
+Reported-by: Michal Kalderon <Michal.Kalderon@cavium.com>
+Fixes: bebd031866ca ("xprtrdma: Support unplugging an HCA from ...")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Cc: stable@vger.kernel.org # v4.12+
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/sunrpc/xprtrdma/verbs.c |   13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+--- a/net/sunrpc/xprtrdma/verbs.c
++++ b/net/sunrpc/xprtrdma/verbs.c
+@@ -250,7 +250,6 @@ rpcrdma_conn_upcall(struct rdma_cm_id *i
+               wait_for_completion(&ia->ri_remove_done);
+               ia->ri_id = NULL;
+-              ia->ri_pd = NULL;
+               ia->ri_device = NULL;
+               /* Return 1 to ensure the core destroys the id. */
+               return 1;
+@@ -445,7 +444,9 @@ rpcrdma_ia_remove(struct rpcrdma_ia *ia)
+               ia->ri_id->qp = NULL;
+       }
+       ib_free_cq(ep->rep_attr.recv_cq);
++      ep->rep_attr.recv_cq = NULL;
+       ib_free_cq(ep->rep_attr.send_cq);
++      ep->rep_attr.send_cq = NULL;
+       /* The ULP is responsible for ensuring all DMA
+        * mappings and MRs are gone.
+@@ -458,6 +459,8 @@ rpcrdma_ia_remove(struct rpcrdma_ia *ia)
+               rpcrdma_dma_unmap_regbuf(req->rl_recvbuf);
+       }
+       rpcrdma_mrs_destroy(buf);
++      ib_dealloc_pd(ia->ri_pd);
++      ia->ri_pd = NULL;
+       /* Allow waiters to continue */
+       complete(&ia->ri_remove_done);
+@@ -628,14 +631,16 @@ rpcrdma_ep_destroy(struct rpcrdma_ep *ep
+ {
+       cancel_delayed_work_sync(&ep->rep_connect_worker);
+-      if (ia->ri_id->qp) {
++      if (ia->ri_id && ia->ri_id->qp) {
+               rpcrdma_ep_disconnect(ep, ia);
+               rdma_destroy_qp(ia->ri_id);
+               ia->ri_id->qp = NULL;
+       }
+-      ib_free_cq(ep->rep_attr.recv_cq);
+-      ib_free_cq(ep->rep_attr.send_cq);
++      if (ep->rep_attr.recv_cq)
++              ib_free_cq(ep->rep_attr.recv_cq);
++      if (ep->rep_attr.send_cq)
++              ib_free_cq(ep->rep_attr.send_cq);
+ }
+ /* Re-establish a connection after a device removal event.
diff --git a/queue-4.16/xprtrdma-fix-latency-regression-on-numa-nfs-rdma-clients.patch b/queue-4.16/xprtrdma-fix-latency-regression-on-numa-nfs-rdma-clients.patch
new file mode 100644 (file)
index 0000000..633e4bb
--- /dev/null
@@ -0,0 +1,85 @@
+From 6720a89933739cb8dec748cd253f7c8df2c0ae4d Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Wed, 28 Feb 2018 15:30:27 -0500
+Subject: xprtrdma: Fix latency regression on NUMA NFS/RDMA clients
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+commit 6720a89933739cb8dec748cd253f7c8df2c0ae4d upstream.
+
+With v4.15, on one of my NFS/RDMA clients I measured a nearly
+doubling in the latency of small read and write system calls. There
+was no change in server round trip time. The extra latency appears
+in the whole RPC execution path.
+
+"git bisect" settled on commit ccede7598588 ("xprtrdma: Spread reply
+processing over more CPUs") .
+
+After some experimentation, I found that leaving the WQ bound and
+allowing the scheduler to pick the dispatch CPU seems to eliminate
+the long latencies, and it does not introduce any new regressions.
+
+The fix is implemented by reverting only the part of
+commit ccede7598588 ("xprtrdma: Spread reply processing over more
+CPUs") that dispatches RPC replies specifically on the CPU where the
+matching RPC call was made.
+
+Interestingly, saving the CPU number and later queuing reply
+processing there was effective _only_ for a NFS READ and WRITE
+request. On my NUMA client, in-kernel RPC reply processing for
+asynchronous RPCs was dispatched on the same CPU where the RPC call
+was made, as expected. However synchronous RPCs seem to get their
+reply dispatched on some other CPU than where the call was placed,
+every time.
+
+Fixes: ccede7598588 ("xprtrdma: Spread reply processing over ... ")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Cc: stable@vger.kernel.org # v4.15+
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/sunrpc/xprtrdma/rpc_rdma.c  |    2 +-
+ net/sunrpc/xprtrdma/transport.c |    2 --
+ net/sunrpc/xprtrdma/xprt_rdma.h |    1 -
+ 3 files changed, 1 insertion(+), 4 deletions(-)
+
+--- a/net/sunrpc/xprtrdma/rpc_rdma.c
++++ b/net/sunrpc/xprtrdma/rpc_rdma.c
+@@ -1366,7 +1366,7 @@ void rpcrdma_reply_handler(struct rpcrdm
+       trace_xprtrdma_reply(rqst->rq_task, rep, req, credits);
+-      queue_work_on(req->rl_cpu, rpcrdma_receive_wq, &rep->rr_work);
++      queue_work(rpcrdma_receive_wq, &rep->rr_work);
+       return;
+ out_badstatus:
+--- a/net/sunrpc/xprtrdma/transport.c
++++ b/net/sunrpc/xprtrdma/transport.c
+@@ -52,7 +52,6 @@
+ #include <linux/slab.h>
+ #include <linux/seq_file.h>
+ #include <linux/sunrpc/addr.h>
+-#include <linux/smp.h>
+ #include "xprt_rdma.h"
+@@ -651,7 +650,6 @@ xprt_rdma_allocate(struct rpc_task *task
+       if (!rpcrdma_get_recvbuf(r_xprt, req, rqst->rq_rcvsize, flags))
+               goto out_fail;
+-      req->rl_cpu = smp_processor_id();
+       req->rl_connect_cookie = 0;     /* our reserved value */
+       rpcrdma_set_xprtdata(rqst, req);
+       rqst->rq_buffer = req->rl_sendbuf->rg_base;
+--- a/net/sunrpc/xprtrdma/xprt_rdma.h
++++ b/net/sunrpc/xprtrdma/xprt_rdma.h
+@@ -334,7 +334,6 @@ enum {
+ struct rpcrdma_buffer;
+ struct rpcrdma_req {
+       struct list_head        rl_list;
+-      int                     rl_cpu;
+       unsigned int            rl_connect_cookie;
+       struct rpcrdma_buffer   *rl_buffer;
+       struct rpcrdma_rep      *rl_reply;