From: Greg Kroah-Hartman Date: Fri, 20 Apr 2018 16:29:14 +0000 (+0200) Subject: 4.16-stable patches X-Git-Tag: v3.18.106~50 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7f30898e28b335540f3582786c0bf69b2a220077;p=thirdparty%2Fkernel%2Fstable-queue.git 4.16-stable patches 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 --- 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 index 00000000000..e4ff5dbcb24 --- /dev/null +++ b/queue-4.16/alsa-pcm-avoid-potential-races-between-oss-ioctls-and-read-write.patch @@ -0,0 +1,376 @@ +From 02a5d6925cd34c3b774bdb8eefb057c40a30e870 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 22 Mar 2018 18:10:14 +0100 +Subject: ALSA: pcm: Avoid potential races between OSS ioctls and read/write + +From: Takashi Iwai + +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: +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..850f7fe1752 --- /dev/null +++ b/queue-4.16/alsa-pcm-fix-endless-loop-for-xrun-recovery-in-oss-emulation.patch @@ -0,0 +1,53 @@ +From e15dc99dbb9cf99f6432e8e3c0b3a8f7a3403a86 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Sat, 7 Apr 2018 11:48:58 +0200 +Subject: ALSA: pcm: Fix endless loop for XRUN recovery in OSS emulation + +From: Takashi Iwai + +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: +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..0643e1b0488 --- /dev/null +++ b/queue-4.16/alsa-pcm-fix-mutex-unbalance-in-oss-emulation-ioctls.patch @@ -0,0 +1,169 @@ +From f6d297df4dd47ef949540e4a201230d0c5308325 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 27 Mar 2018 14:32:23 +0200 +Subject: ALSA: pcm: Fix mutex unbalance in OSS emulation ioctls + +From: Takashi Iwai + +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 +Cc: +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..0ab33b3c845 --- /dev/null +++ b/queue-4.16/alsa-pcm-fix-uaf-at-pcm-release-via-pcm-timer-access.patch @@ -0,0 +1,59 @@ +From a820ccbe21e8ce8e86c39cd1d3bc8c7d1cbb949b Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 2 Apr 2018 22:41:43 +0200 +Subject: ALSA: pcm: Fix UAF at PCM release via PCM timer access + +From: Takashi Iwai + +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: +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + 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 + #include + #include ++#include + #include + #include + +@@ -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 index 00000000000..b38fd91c5f6 --- /dev/null +++ b/queue-4.16/alsa-pcm-return-ebusy-for-oss-ioctls-changing-busy-streams.patch @@ -0,0 +1,182 @@ +From 40cab6e88cb0b6c56d3f30b7491a20e803f948f6 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Fri, 23 Mar 2018 08:03:26 +0100 +Subject: ALSA: pcm: Return -EBUSY for OSS ioctls changing busy streams + +From: Takashi Iwai + +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: +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..50212441882 --- /dev/null +++ b/queue-4.16/cxl-fix-possible-deadlock-when-processing-page-faults-from-cxllib.patch @@ -0,0 +1,154 @@ +From ad7b4e8022b9864c075fe71e1328b1d25cad82f6 Mon Sep 17 00:00:00 2001 +From: Frederic Barrat +Date: Tue, 3 Apr 2018 15:54:02 +0200 +Subject: cxl: Fix possible deadlock when processing page faults from cxllib + +From: Frederic Barrat + +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 +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..9e5f844903e --- /dev/null +++ b/queue-4.16/dm-backfill-abnormal-io-support-to-non-splitting-io-submission.patch @@ -0,0 +1,79 @@ +From 0519c71e8d461ac3ef9a555bb7339243c9128d37 Mon Sep 17 00:00:00 2001 +From: Mike Snitzer +Date: Mon, 26 Mar 2018 11:49:16 -0400 +Subject: dm: backfill abnormal IO support to non-splitting IO submission + +From: Mike Snitzer + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..d7ace67bd01 --- /dev/null +++ b/queue-4.16/dm-crypt-limit-the-number-of-allocated-pages.patch @@ -0,0 +1,151 @@ +From 5059353df86e2573ccd9d43fd9d9396dcec47ca2 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Sun, 13 Aug 2017 22:45:08 -0400 +Subject: dm crypt: limit the number of allocated pages + +From: Mikulas Patocka + +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 +Signed-off-by: Mike Snitzer +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..d17574e03b6 --- /dev/null +++ b/queue-4.16/dm-raid-fix-nosync-status.patch @@ -0,0 +1,35 @@ +From 880bcce0dcc3172fe865352b492c41d85290cb8d Mon Sep 17 00:00:00 2001 +From: Heinz Mauelshagen +Date: Fri, 16 Mar 2018 23:01:59 +0100 +Subject: dm raid: fix nosync status + +From: Heinz Mauelshagen + +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 +Signed-off-by: Mike Snitzer +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..ad4f608e5f8 --- /dev/null +++ b/queue-4.16/dmaengine-at_xdmac-fix-rare-residue-corruption.patch @@ -0,0 +1,71 @@ +From c5637476bbf9bb86c7f0413b8f4822a73d8d2d07 Mon Sep 17 00:00:00 2001 +From: Maxime Jayat +Date: Thu, 22 Feb 2018 12:39:55 +0100 +Subject: dmaengine: at_xdmac: fix rare residue corruption + +From: Maxime Jayat + +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 +Acked-by: Ludovic Desroches +Signed-off-by: Vinod Koul +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..0d1be87eda3 --- /dev/null +++ b/queue-4.16/drivers-infiniband-core-verbs.c-fix-build-with-gcc-4.4.4.patch @@ -0,0 +1,44 @@ +From 6ee687735e745eafae9e6b93d1ea70bc52e7ad07 Mon Sep 17 00:00:00 2001 +From: Andrew Morton +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 + +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 +Cc: Steve Wise +Cc: Sagi Grimberg +Cc: Jason Gunthorpe +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Doug Ledford +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..0a647e6b5db --- /dev/null +++ b/queue-4.16/drivers-infiniband-ulp-srpt-ib_srpt.c-fix-build-with-gcc-4.4.4.patch @@ -0,0 +1,43 @@ +From 06892cc190550807d332c95a0114c7e175584012 Mon Sep 17 00:00:00 2001 +From: Andrew Morton +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 + +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 +Cc: Christoph Hellwig +Cc: Jason Gunthorpe +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Doug Ledford +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..0b9ca8e40d2 --- /dev/null +++ b/queue-4.16/ib-srp-fix-completion-vector-assignment-algorithm.patch @@ -0,0 +1,49 @@ +From 3a148896b24adf8688dc0c59af54531931677a40 Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Mon, 12 Feb 2018 09:50:25 -0800 +Subject: IB/srp: Fix completion vector assignment algorithm + +From: Bart Van Assche + +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 +Signed-off-by: Bart Van Assche +Cc: Alexander Schmid +Cc: stable@vger.kernel.org +Signed-off-by: Jason Gunthorpe +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..03fdf2d83a3 --- /dev/null +++ b/queue-4.16/ib-srp-fix-srp_abort.patch @@ -0,0 +1,41 @@ +From e68088e78d82920632eba112b968e49d588d02a2 Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Fri, 23 Feb 2018 14:09:24 -0800 +Subject: IB/srp: Fix srp_abort() + +From: Bart Van Assche + +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 +Cc: stable@vger.kernel.org +Signed-off-by: Jason Gunthorpe +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..e6f3ff3824e --- /dev/null +++ b/queue-4.16/ib-srpt-fix-an-out-of-bounds-stack-access-in-srpt_zerolength_write.patch @@ -0,0 +1,74 @@ +From 2a78cb4db487372152bed2055c038f9634d595e8 Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +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 + +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 +Cc: Christoph Hellwig +Cc: stable@vger.kernel.org +Signed-off-by: Jason Gunthorpe +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..73cd2a81eb1 --- /dev/null +++ b/queue-4.16/libnvdimm-dimm-fix-dpa-reservation-vs-uninitialized-label-area.patch @@ -0,0 +1,51 @@ +From c31898c8c711f2bbbcaebe802a55827e288d875a Mon Sep 17 00:00:00 2001 +From: Dan Williams +Date: Fri, 6 Apr 2018 11:25:38 -0700 +Subject: libnvdimm, dimm: fix dpa reservation vs uninitialized label area + +From: Dan Williams + +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: +Fixes: 4a826c83db4e ("libnvdimm: namespace indices: read and validate") +Reported-by: Krzysztof Rusocki +Signed-off-by: Dan Williams +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..f6e575890aa --- /dev/null +++ b/queue-4.16/libnvdimm-namespace-use-a-safe-lookup-for-dimm-device-name.patch @@ -0,0 +1,70 @@ +From 4f8672201b7e7ed4f5f6c3cf6dcd080648580582 Mon Sep 17 00:00:00 2001 +From: Dan Williams +Date: Fri, 6 Apr 2018 16:37:21 -0700 +Subject: libnvdimm, namespace: use a safe lookup for dimm device name + +From: Dan Williams + +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: +Reported-by: Dave Jiang +Signed-off-by: Dan Williams +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..7dd71973986 --- /dev/null +++ b/queue-4.16/rdma-core-avoid-that-ib_drain_qp-triggers-an-out-of-bounds-stack-access.patch @@ -0,0 +1,92 @@ +From a1ae7d0345edd593d6725d3218434d903a0af95d Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +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 + +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 +Cc: Steve Wise +Cc: Sagi Grimberg +Cc: stable@vger.kernel.org +Signed-off-by: Jason Gunthorpe +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..314e28d3a0d --- /dev/null +++ b/queue-4.16/rdma-mlx5-protect-from-null-pointer-derefence.patch @@ -0,0 +1,35 @@ +From 4289861d88d6c7b5e4c8cc7fe2ad6cdf0cdfc366 Mon Sep 17 00:00:00 2001 +From: Leon Romanovsky +Date: Tue, 13 Mar 2018 15:29:24 +0200 +Subject: RDMA/mlx5: Protect from NULL pointer derefence + +From: Leon Romanovsky + +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: # 4.10 +Fixes: 81713d3788d2 ("IB/mlx5: Add implicit MR support") +Reported-by: Noa Osherovich +Signed-off-by: Leon Romanovsky +Signed-off-by: Doug Ledford +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..2f2666fe980 --- /dev/null +++ b/queue-4.16/rdma-rxe-fix-an-out-of-bounds-read.patch @@ -0,0 +1,88 @@ +From a6544a624c3ff92a64e4aca3931fa064607bd3da Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Thu, 1 Mar 2018 14:00:29 -0800 +Subject: RDMA/rxe: Fix an out-of-bounds read + +From: Bart Van Assche + +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 +Cc: Moni Shoua +Cc: stable@vger.kernel.org +Signed-off-by: Jason Gunthorpe +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..16df36df609 --- /dev/null +++ b/queue-4.16/rdma-ucma-don-t-allow-setting-rdma_option_ib_path-without-an-rdma-device.patch @@ -0,0 +1,35 @@ +From 8435168d50e66fa5eae01852769d20a36f9e5e83 Mon Sep 17 00:00:00 2001 +From: Roland Dreier +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 + +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: +Reported-by: +Signed-off-by: Roland Dreier +Signed-off-by: Jason Gunthorpe +Signed-off-by: Greg Kroah-Hartman + +--- + 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; diff --git a/queue-4.16/series b/queue-4.16/series index 8c6ec04844f..2a11eab1f68 100644 --- a/queue-4.16/series +++ b/queue-4.16/series @@ -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 index 00000000000..6ac53dbd34e --- /dev/null +++ b/queue-4.16/tpm-self-test-failure-should-not-cause-suspend-to-fail.patch @@ -0,0 +1,60 @@ +From 0803d7befa15cab5717d667a97a66214d2a4c083 Mon Sep 17 00:00:00 2001 +From: Chris Chiu +Date: Tue, 20 Mar 2018 15:36:40 +0800 +Subject: tpm: self test failure should not cause suspend to fail + +From: Chris Chiu + +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 +Signed-off-by: Daniel Drake +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 +Signed-off-by: Jarkko Sakkinen +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..4d12061a58c --- /dev/null +++ b/queue-4.16/vsprintf-do-not-preprocess-non-dereferenced-pointers-for-bprintf-px-and-pk.patch @@ -0,0 +1,45 @@ +From 1e6338cfb50e244c445ad7d891b35385bd0ee757 Mon Sep 17 00:00:00 2001 +From: "Steven Rostedt (VMware)" +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) + +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) +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..5da541ab5f1 --- /dev/null +++ b/queue-4.16/xprtrdma-fix-corner-cases-when-handling-device-removal.patch @@ -0,0 +1,83 @@ +From 25524288631fc5b7d33259fca1e0dc38146be5d6 Mon Sep 17 00:00:00 2001 +From: Chuck Lever +Date: Mon, 19 Mar 2018 14:23:16 -0400 +Subject: xprtrdma: Fix corner cases when handling device removal + +From: Chuck Lever + +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 +Fixes: bebd031866ca ("xprtrdma: Support unplugging an HCA from ...") +Signed-off-by: Chuck Lever +Cc: stable@vger.kernel.org # v4.12+ +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..633e4bb8cb3 --- /dev/null +++ b/queue-4.16/xprtrdma-fix-latency-regression-on-numa-nfs-rdma-clients.patch @@ -0,0 +1,85 @@ +From 6720a89933739cb8dec748cd253f7c8df2c0ae4d Mon Sep 17 00:00:00 2001 +From: Chuck Lever +Date: Wed, 28 Feb 2018 15:30:27 -0500 +Subject: xprtrdma: Fix latency regression on NUMA NFS/RDMA clients + +From: Chuck Lever + +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 +Cc: stable@vger.kernel.org # v4.15+ +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman + +--- + 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 + #include + #include +-#include + + #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;