From b183e76a10954e2cf177ee9641db0b01eeba823d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 10 May 2022 13:40:39 +0200 Subject: [PATCH] 5.4-stable patches added patches: alsa-pcm-fix-potential-ab-ba-lock-with-buffer_mutex-and-mmap_lock.patch alsa-pcm-fix-races-among-concurrent-hw_params-and-hw_free-calls.patch alsa-pcm-fix-races-among-concurrent-prealloc-proc-writes.patch alsa-pcm-fix-races-among-concurrent-prepare-and-hw_params-hw_free-calls.patch alsa-pcm-fix-races-among-concurrent-read-write-and-buffer-changes.patch tcp-make-sure-treq-af_specific-is-initialized.patch --- ...lock-with-buffer_mutex-and-mmap_lock.patch | 214 ++++++++++++++++++ ...ncurrent-hw_params-and-hw_free-calls.patch | 175 ++++++++++++++ ...mong-concurrent-prealloc-proc-writes.patch | 73 ++++++ ...-prepare-and-hw_params-hw_free-calls.patch | 102 +++++++++ ...urrent-read-write-and-buffer-changes.patch | 64 ++++++ queue-5.4/series | 6 + ...sure-treq-af_specific-is-initialized.patch | 143 ++++++++++++ 7 files changed, 777 insertions(+) create mode 100644 queue-5.4/alsa-pcm-fix-potential-ab-ba-lock-with-buffer_mutex-and-mmap_lock.patch create mode 100644 queue-5.4/alsa-pcm-fix-races-among-concurrent-hw_params-and-hw_free-calls.patch create mode 100644 queue-5.4/alsa-pcm-fix-races-among-concurrent-prealloc-proc-writes.patch create mode 100644 queue-5.4/alsa-pcm-fix-races-among-concurrent-prepare-and-hw_params-hw_free-calls.patch create mode 100644 queue-5.4/alsa-pcm-fix-races-among-concurrent-read-write-and-buffer-changes.patch create mode 100644 queue-5.4/tcp-make-sure-treq-af_specific-is-initialized.patch diff --git a/queue-5.4/alsa-pcm-fix-potential-ab-ba-lock-with-buffer_mutex-and-mmap_lock.patch b/queue-5.4/alsa-pcm-fix-potential-ab-ba-lock-with-buffer_mutex-and-mmap_lock.patch new file mode 100644 index 00000000000..508c2d1da51 --- /dev/null +++ b/queue-5.4/alsa-pcm-fix-potential-ab-ba-lock-with-buffer_mutex-and-mmap_lock.patch @@ -0,0 +1,214 @@ +From foo@baz Tue May 10 01:32:04 PM CEST 2022 +From: Ovidiu Panait +Date: Fri, 6 May 2022 12:10:13 +0300 +Subject: ALSA: pcm: Fix potential AB/BA lock with buffer_mutex and mmap_lock +To: stable@vger.kernel.org +Cc: tiwai@suse.de, perex@perex.cz, kirin.say@gmail.com +Message-ID: <20220506091013.1746159-6-ovidiu.panait@windriver.com> + +From: Takashi Iwai + +commit bc55cfd5718c7c23e5524582e9fa70b4d10f2433 upstream. + +syzbot caught a potential deadlock between the PCM +runtime->buffer_mutex and the mm->mmap_lock. It was brought by the +recent fix to cover the racy read/write and other ioctls, and in that +commit, I overlooked a (hopefully only) corner case that may take the +revert lock, namely, the OSS mmap. The OSS mmap operation +exceptionally allows to re-configure the parameters inside the OSS +mmap syscall, where mm->mmap_mutex is already held. Meanwhile, the +copy_from/to_user calls at read/write operations also take the +mm->mmap_lock internally, hence it may lead to a AB/BA deadlock. + +A similar problem was already seen in the past and we fixed it with a +refcount (in commit b248371628aa). The former fix covered only the +call paths with OSS read/write and OSS ioctls, while we need to cover +the concurrent access via both ALSA and OSS APIs now. + +This patch addresses the problem above by replacing the buffer_mutex +lock in the read/write operations with a refcount similar as we've +used for OSS. The new field, runtime->buffer_accessing, keeps the +number of concurrent read/write operations. Unlike the former +buffer_mutex protection, this protects only around the +copy_from/to_user() calls; the other codes are basically protected by +the PCM stream lock. The refcount can be a negative, meaning blocked +by the ioctls. If a negative value is seen, the read/write aborts +with -EBUSY. In the ioctl side, OTOH, they check this refcount, too, +and set to a negative value for blocking unless it's already being +accessed. + +Reported-by: syzbot+6e5c88838328e99c7e1c@syzkaller.appspotmail.com +Fixes: dca947d4d26d ("ALSA: pcm: Fix races among concurrent read/write and buffer changes") +Cc: +Link: https://lore.kernel.org/r/000000000000381a0d05db622a81@google.com +Link: https://lore.kernel.org/r/20220330120903.4738-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +[OP: backport to 5.4: adjusted context] +Signed-off-by: Ovidiu Panait +Signed-off-by: Greg Kroah-Hartman +--- + include/sound/pcm.h | 1 + + sound/core/pcm.c | 1 + + sound/core/pcm_lib.c | 9 +++++---- + sound/core/pcm_native.c | 39 ++++++++++++++++++++++++++++++++------- + 4 files changed, 39 insertions(+), 11 deletions(-) + +--- a/include/sound/pcm.h ++++ b/include/sound/pcm.h +@@ -396,6 +396,7 @@ struct snd_pcm_runtime { + wait_queue_head_t tsleep; /* transfer sleep */ + struct fasync_struct *fasync; + struct mutex buffer_mutex; /* protect for buffer changes */ ++ atomic_t buffer_accessing; /* >0: in r/w operation, <0: blocked */ + + /* -- private section -- */ + void *private_data; +--- a/sound/core/pcm.c ++++ b/sound/core/pcm.c +@@ -970,6 +970,7 @@ int snd_pcm_attach_substream(struct snd_ + + runtime->status->state = SNDRV_PCM_STATE_OPEN; + mutex_init(&runtime->buffer_mutex); ++ atomic_set(&runtime->buffer_accessing, 0); + + substream->runtime = runtime; + substream->private_data = pcm->private_data; +--- a/sound/core/pcm_lib.c ++++ b/sound/core/pcm_lib.c +@@ -1861,11 +1861,9 @@ static int wait_for_avail(struct snd_pcm + if (avail >= runtime->twake) + break; + snd_pcm_stream_unlock_irq(substream); +- mutex_unlock(&runtime->buffer_mutex); + + tout = schedule_timeout(wait_time); + +- mutex_lock(&runtime->buffer_mutex); + snd_pcm_stream_lock_irq(substream); + set_current_state(TASK_INTERRUPTIBLE); + switch (runtime->status->state) { +@@ -2159,7 +2157,6 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(str + + nonblock = !!(substream->f_flags & O_NONBLOCK); + +- mutex_lock(&runtime->buffer_mutex); + snd_pcm_stream_lock_irq(substream); + err = pcm_accessible_state(runtime); + if (err < 0) +@@ -2214,10 +2211,15 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(str + err = -EINVAL; + goto _end_unlock; + } ++ if (!atomic_inc_unless_negative(&runtime->buffer_accessing)) { ++ err = -EBUSY; ++ goto _end_unlock; ++ } + snd_pcm_stream_unlock_irq(substream); + err = writer(substream, appl_ofs, data, offset, frames, + transfer); + snd_pcm_stream_lock_irq(substream); ++ atomic_dec(&runtime->buffer_accessing); + if (err < 0) + goto _end_unlock; + err = pcm_accessible_state(runtime); +@@ -2247,7 +2249,6 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(str + if (xfer > 0 && err >= 0) + snd_pcm_update_state(substream, runtime); + snd_pcm_stream_unlock_irq(substream); +- mutex_unlock(&runtime->buffer_mutex); + return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; + } + EXPORT_SYMBOL(__snd_pcm_lib_xfer); +--- a/sound/core/pcm_native.c ++++ b/sound/core/pcm_native.c +@@ -630,6 +630,24 @@ static int snd_pcm_hw_params_choose(stru + return 0; + } + ++/* acquire buffer_mutex; if it's in r/w operation, return -EBUSY, otherwise ++ * block the further r/w operations ++ */ ++static int snd_pcm_buffer_access_lock(struct snd_pcm_runtime *runtime) ++{ ++ if (!atomic_dec_unless_positive(&runtime->buffer_accessing)) ++ return -EBUSY; ++ mutex_lock(&runtime->buffer_mutex); ++ return 0; /* keep buffer_mutex, unlocked by below */ ++} ++ ++/* release buffer_mutex and clear r/w access flag */ ++static void snd_pcm_buffer_access_unlock(struct snd_pcm_runtime *runtime) ++{ ++ mutex_unlock(&runtime->buffer_mutex); ++ atomic_inc(&runtime->buffer_accessing); ++} ++ + #if IS_ENABLED(CONFIG_SND_PCM_OSS) + #define is_oss_stream(substream) ((substream)->oss.oss) + #else +@@ -640,14 +658,16 @@ static int snd_pcm_hw_params(struct snd_ + struct snd_pcm_hw_params *params) + { + struct snd_pcm_runtime *runtime; +- int err = 0, usecs; ++ int err, usecs; + unsigned int bits; + snd_pcm_uframes_t frames; + + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; + runtime = substream->runtime; +- mutex_lock(&runtime->buffer_mutex); ++ err = snd_pcm_buffer_access_lock(runtime); ++ if (err < 0) ++ return err; + snd_pcm_stream_lock_irq(substream); + switch (runtime->status->state) { + case SNDRV_PCM_STATE_OPEN: +@@ -752,7 +772,7 @@ static int snd_pcm_hw_params(struct snd_ + substream->ops->hw_free(substream); + } + unlock: +- mutex_unlock(&runtime->buffer_mutex); ++ snd_pcm_buffer_access_unlock(runtime); + return err; + } + +@@ -785,7 +805,9 @@ static int snd_pcm_hw_free(struct snd_pc + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; + runtime = substream->runtime; +- mutex_lock(&runtime->buffer_mutex); ++ result = snd_pcm_buffer_access_lock(runtime); ++ if (result < 0) ++ return result; + snd_pcm_stream_lock_irq(substream); + switch (runtime->status->state) { + case SNDRV_PCM_STATE_SETUP: +@@ -805,7 +827,7 @@ static int snd_pcm_hw_free(struct snd_pc + snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); + pm_qos_remove_request(&substream->latency_pm_qos_req); + unlock: +- mutex_unlock(&runtime->buffer_mutex); ++ snd_pcm_buffer_access_unlock(runtime); + return result; + } + +@@ -1221,12 +1243,15 @@ static int snd_pcm_action_nonatomic(cons + + /* Guarantee the group members won't change during non-atomic action */ + down_read(&snd_pcm_link_rwsem); +- mutex_lock(&substream->runtime->buffer_mutex); ++ res = snd_pcm_buffer_access_lock(substream->runtime); ++ if (res < 0) ++ goto unlock; + if (snd_pcm_stream_linked(substream)) + res = snd_pcm_action_group(ops, substream, state, 0); + else + res = snd_pcm_action_single(ops, substream, state); +- mutex_unlock(&substream->runtime->buffer_mutex); ++ snd_pcm_buffer_access_unlock(substream->runtime); ++ unlock: + up_read(&snd_pcm_link_rwsem); + return res; + } diff --git a/queue-5.4/alsa-pcm-fix-races-among-concurrent-hw_params-and-hw_free-calls.patch b/queue-5.4/alsa-pcm-fix-races-among-concurrent-hw_params-and-hw_free-calls.patch new file mode 100644 index 00000000000..5761591f892 --- /dev/null +++ b/queue-5.4/alsa-pcm-fix-races-among-concurrent-hw_params-and-hw_free-calls.patch @@ -0,0 +1,175 @@ +From foo@baz Tue May 10 01:32:04 PM CEST 2022 +From: Ovidiu Panait +Date: Fri, 6 May 2022 12:10:09 +0300 +Subject: ALSA: pcm: Fix races among concurrent hw_params and hw_free calls +To: stable@vger.kernel.org +Cc: tiwai@suse.de, perex@perex.cz, kirin.say@gmail.com +Message-ID: <20220506091013.1746159-2-ovidiu.panait@windriver.com> + +From: Takashi Iwai + +commit 92ee3c60ec9fe64404dc035e7c41277d74aa26cb upstream. + +Currently we have neither proper check nor protection against the +concurrent calls of PCM hw_params and hw_free ioctls, which may result +in a UAF. Since the existing PCM stream lock can't be used for +protecting the whole ioctl operations, we need a new mutex to protect +those racy calls. + +This patch introduced a new mutex, runtime->buffer_mutex, and applies +it to both hw_params and hw_free ioctl code paths. Along with it, the +both functions are slightly modified (the mmap_count check is moved +into the state-check block) for code simplicity. + +Reported-by: Hu Jiahui +Cc: +Reviewed-by: Jaroslav Kysela +Link: https://lore.kernel.org/r/20220322170720.3529-2-tiwai@suse.de +Signed-off-by: Takashi Iwai +[OP: backport to 5.4: adjusted context] +Signed-off-by: Ovidiu Panait +Signed-off-by: Greg Kroah-Hartman +--- + include/sound/pcm.h | 1 + sound/core/pcm.c | 2 + + sound/core/pcm_native.c | 55 +++++++++++++++++++++++++++++++----------------- + 3 files changed, 39 insertions(+), 19 deletions(-) + +--- a/include/sound/pcm.h ++++ b/include/sound/pcm.h +@@ -395,6 +395,7 @@ struct snd_pcm_runtime { + wait_queue_head_t sleep; /* poll sleep */ + wait_queue_head_t tsleep; /* transfer sleep */ + struct fasync_struct *fasync; ++ struct mutex buffer_mutex; /* protect for buffer changes */ + + /* -- private section -- */ + void *private_data; +--- a/sound/core/pcm.c ++++ b/sound/core/pcm.c +@@ -969,6 +969,7 @@ int snd_pcm_attach_substream(struct snd_ + init_waitqueue_head(&runtime->tsleep); + + runtime->status->state = SNDRV_PCM_STATE_OPEN; ++ mutex_init(&runtime->buffer_mutex); + + substream->runtime = runtime; + substream->private_data = pcm->private_data; +@@ -1000,6 +1001,7 @@ void snd_pcm_detach_substream(struct snd + substream->runtime = NULL; + if (substream->timer) + spin_unlock_irq(&substream->timer->lock); ++ mutex_destroy(&runtime->buffer_mutex); + kfree(runtime); + put_pid(substream->pid); + substream->pid = NULL; +--- a/sound/core/pcm_native.c ++++ b/sound/core/pcm_native.c +@@ -630,33 +630,40 @@ static int snd_pcm_hw_params_choose(stru + return 0; + } + ++#if IS_ENABLED(CONFIG_SND_PCM_OSS) ++#define is_oss_stream(substream) ((substream)->oss.oss) ++#else ++#define is_oss_stream(substream) false ++#endif ++ + static int snd_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) + { + struct snd_pcm_runtime *runtime; +- int err, usecs; ++ int err = 0, usecs; + unsigned int bits; + snd_pcm_uframes_t frames; + + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; + runtime = substream->runtime; ++ mutex_lock(&runtime->buffer_mutex); + snd_pcm_stream_lock_irq(substream); + switch (runtime->status->state) { + case SNDRV_PCM_STATE_OPEN: + case SNDRV_PCM_STATE_SETUP: + case SNDRV_PCM_STATE_PREPARED: ++ if (!is_oss_stream(substream) && ++ atomic_read(&substream->mmap_count)) ++ err = -EBADFD; + break; + default: +- snd_pcm_stream_unlock_irq(substream); +- return -EBADFD; ++ err = -EBADFD; ++ break; + } + snd_pcm_stream_unlock_irq(substream); +-#if IS_ENABLED(CONFIG_SND_PCM_OSS) +- if (!substream->oss.oss) +-#endif +- if (atomic_read(&substream->mmap_count)) +- return -EBADFD; ++ if (err) ++ goto unlock; + + params->rmask = ~0U; + err = snd_pcm_hw_refine(substream, params); +@@ -733,14 +740,19 @@ static int snd_pcm_hw_params(struct snd_ + if ((usecs = period_to_usecs(runtime)) >= 0) + pm_qos_add_request(&substream->latency_pm_qos_req, + PM_QOS_CPU_DMA_LATENCY, usecs); +- return 0; ++ err = 0; + _error: +- /* hardware might be unusable from this time, +- so we force application to retry to set +- the correct hardware parameter settings */ +- snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); +- if (substream->ops->hw_free != NULL) +- substream->ops->hw_free(substream); ++ if (err) { ++ /* hardware might be unusable from this time, ++ * so we force application to retry to set ++ * the correct hardware parameter settings ++ */ ++ snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); ++ if (substream->ops->hw_free != NULL) ++ substream->ops->hw_free(substream); ++ } ++ unlock: ++ mutex_unlock(&runtime->buffer_mutex); + return err; + } + +@@ -773,22 +785,27 @@ static int snd_pcm_hw_free(struct snd_pc + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; + runtime = substream->runtime; ++ mutex_lock(&runtime->buffer_mutex); + snd_pcm_stream_lock_irq(substream); + switch (runtime->status->state) { + case SNDRV_PCM_STATE_SETUP: + case SNDRV_PCM_STATE_PREPARED: ++ if (atomic_read(&substream->mmap_count)) ++ result = -EBADFD; + break; + default: +- snd_pcm_stream_unlock_irq(substream); +- return -EBADFD; ++ result = -EBADFD; ++ break; + } + snd_pcm_stream_unlock_irq(substream); +- if (atomic_read(&substream->mmap_count)) +- return -EBADFD; ++ if (result) ++ goto unlock; + if (substream->ops->hw_free) + result = substream->ops->hw_free(substream); + snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); + pm_qos_remove_request(&substream->latency_pm_qos_req); ++ unlock: ++ mutex_unlock(&runtime->buffer_mutex); + return result; + } + diff --git a/queue-5.4/alsa-pcm-fix-races-among-concurrent-prealloc-proc-writes.patch b/queue-5.4/alsa-pcm-fix-races-among-concurrent-prealloc-proc-writes.patch new file mode 100644 index 00000000000..9ca2687f7c0 --- /dev/null +++ b/queue-5.4/alsa-pcm-fix-races-among-concurrent-prealloc-proc-writes.patch @@ -0,0 +1,73 @@ +From foo@baz Tue May 10 01:32:04 PM CEST 2022 +From: Ovidiu Panait +Date: Fri, 6 May 2022 12:10:12 +0300 +Subject: ALSA: pcm: Fix races among concurrent prealloc proc writes +To: stable@vger.kernel.org +Cc: tiwai@suse.de, perex@perex.cz, kirin.say@gmail.com +Message-ID: <20220506091013.1746159-5-ovidiu.panait@windriver.com> + +From: Takashi Iwai + +commit 69534c48ba8ce552ce383b3dfdb271ffe51820c3 upstream. + +We have no protection against concurrent PCM buffer preallocation +changes via proc files, and it may potentially lead to UAF or some +weird problem. This patch applies the PCM open_mutex to the proc +write operation for avoiding the racy proc writes and the PCM stream +open (and further operations). + +Cc: +Reviewed-by: Jaroslav Kysela +Link: https://lore.kernel.org/r/20220322170720.3529-5-tiwai@suse.de +Signed-off-by: Takashi Iwai +[OP: backport to 5.4: adjusted context] +Signed-off-by: Ovidiu Panait +Signed-off-by: Greg Kroah-Hartman +--- + sound/core/pcm_memory.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +--- a/sound/core/pcm_memory.c ++++ b/sound/core/pcm_memory.c +@@ -133,19 +133,20 @@ static void snd_pcm_lib_preallocate_proc + size_t size; + struct snd_dma_buffer new_dmab; + ++ mutex_lock(&substream->pcm->open_mutex); + if (substream->runtime) { + buffer->error = -EBUSY; +- return; ++ goto unlock; + } + if (!snd_info_get_line(buffer, line, sizeof(line))) { + snd_info_get_str(str, line, sizeof(str)); + size = simple_strtoul(str, NULL, 10) * 1024; + if ((size != 0 && size < 8192) || size > substream->dma_max) { + buffer->error = -EINVAL; +- return; ++ goto unlock; + } + if (substream->dma_buffer.bytes == size) +- return; ++ goto unlock; + memset(&new_dmab, 0, sizeof(new_dmab)); + new_dmab.dev = substream->dma_buffer.dev; + if (size > 0) { +@@ -153,7 +154,7 @@ static void snd_pcm_lib_preallocate_proc + substream->dma_buffer.dev.dev, + size, &new_dmab) < 0) { + buffer->error = -ENOMEM; +- return; ++ goto unlock; + } + substream->buffer_bytes_max = size; + } else { +@@ -165,6 +166,8 @@ static void snd_pcm_lib_preallocate_proc + } else { + buffer->error = -EINVAL; + } ++ unlock: ++ mutex_unlock(&substream->pcm->open_mutex); + } + + static inline void preallocate_info_init(struct snd_pcm_substream *substream) diff --git a/queue-5.4/alsa-pcm-fix-races-among-concurrent-prepare-and-hw_params-hw_free-calls.patch b/queue-5.4/alsa-pcm-fix-races-among-concurrent-prepare-and-hw_params-hw_free-calls.patch new file mode 100644 index 00000000000..093b43a50ec --- /dev/null +++ b/queue-5.4/alsa-pcm-fix-races-among-concurrent-prepare-and-hw_params-hw_free-calls.patch @@ -0,0 +1,102 @@ +From foo@baz Tue May 10 01:32:04 PM CEST 2022 +From: Ovidiu Panait +Date: Fri, 6 May 2022 12:10:11 +0300 +Subject: ALSA: pcm: Fix races among concurrent prepare and hw_params/hw_free calls +To: stable@vger.kernel.org +Cc: tiwai@suse.de, perex@perex.cz, kirin.say@gmail.com +Message-ID: <20220506091013.1746159-4-ovidiu.panait@windriver.com> + +From: Takashi Iwai + +commit 3c3201f8c7bb77eb53b08a3ca8d9a4ddc500b4c0 upstream. + +Like the previous fixes to hw_params and hw_free ioctl races, we need +to paper over the concurrent prepare ioctl calls against hw_params and +hw_free, too. + +This patch implements the locking with the existing +runtime->buffer_mutex for prepare ioctls. Unlike the previous case +for snd_pcm_hw_hw_params() and snd_pcm_hw_free(), snd_pcm_prepare() is +performed to the linked streams, hence the lock can't be applied +simply on the top. For tracking the lock in each linked substream, we +modify snd_pcm_action_group() slightly and apply the buffer_mutex for +the case stream_lock=false (formerly there was no lock applied) +there. + +Cc: +Reviewed-by: Jaroslav Kysela +Link: https://lore.kernel.org/r/20220322170720.3529-4-tiwai@suse.de +Signed-off-by: Takashi Iwai +[OP: backport to 5.4: adjusted context] +Signed-off-by: Ovidiu Panait +Signed-off-by: Greg Kroah-Hartman +--- + sound/core/pcm_native.c | 32 ++++++++++++++++++-------------- + 1 file changed, 18 insertions(+), 14 deletions(-) + +--- a/sound/core/pcm_native.c ++++ b/sound/core/pcm_native.c +@@ -1042,15 +1042,17 @@ struct action_ops { + */ + static int snd_pcm_action_group(const struct action_ops *ops, + struct snd_pcm_substream *substream, +- int state, int do_lock) ++ int state, int stream_lock) + { + struct snd_pcm_substream *s = NULL; + struct snd_pcm_substream *s1; + int res = 0, depth = 1; + + snd_pcm_group_for_each_entry(s, substream) { +- if (do_lock && s != substream) { +- if (s->pcm->nonatomic) ++ if (s != substream) { ++ if (!stream_lock) ++ mutex_lock_nested(&s->runtime->buffer_mutex, depth); ++ else if (s->pcm->nonatomic) + mutex_lock_nested(&s->self_group.mutex, depth); + else + spin_lock_nested(&s->self_group.lock, depth); +@@ -1078,18 +1080,18 @@ static int snd_pcm_action_group(const st + ops->post_action(s, state); + } + _unlock: +- if (do_lock) { +- /* unlock streams */ +- snd_pcm_group_for_each_entry(s1, substream) { +- if (s1 != substream) { +- if (s1->pcm->nonatomic) +- mutex_unlock(&s1->self_group.mutex); +- else +- spin_unlock(&s1->self_group.lock); +- } +- if (s1 == s) /* end */ +- break; ++ /* unlock streams */ ++ snd_pcm_group_for_each_entry(s1, substream) { ++ if (s1 != substream) { ++ if (!stream_lock) ++ mutex_unlock(&s1->runtime->buffer_mutex); ++ else if (s1->pcm->nonatomic) ++ mutex_unlock(&s1->self_group.mutex); ++ else ++ spin_unlock(&s1->self_group.lock); + } ++ if (s1 == s) /* end */ ++ break; + } + return res; + } +@@ -1219,10 +1221,12 @@ static int snd_pcm_action_nonatomic(cons + + /* Guarantee the group members won't change during non-atomic action */ + down_read(&snd_pcm_link_rwsem); ++ mutex_lock(&substream->runtime->buffer_mutex); + if (snd_pcm_stream_linked(substream)) + res = snd_pcm_action_group(ops, substream, state, 0); + else + res = snd_pcm_action_single(ops, substream, state); ++ mutex_unlock(&substream->runtime->buffer_mutex); + up_read(&snd_pcm_link_rwsem); + return res; + } diff --git a/queue-5.4/alsa-pcm-fix-races-among-concurrent-read-write-and-buffer-changes.patch b/queue-5.4/alsa-pcm-fix-races-among-concurrent-read-write-and-buffer-changes.patch new file mode 100644 index 00000000000..d2cfe2dad74 --- /dev/null +++ b/queue-5.4/alsa-pcm-fix-races-among-concurrent-read-write-and-buffer-changes.patch @@ -0,0 +1,64 @@ +From foo@baz Tue May 10 01:32:04 PM CEST 2022 +From: Ovidiu Panait +Date: Fri, 6 May 2022 12:10:10 +0300 +Subject: ALSA: pcm: Fix races among concurrent read/write and buffer changes +To: stable@vger.kernel.org +Cc: tiwai@suse.de, perex@perex.cz, kirin.say@gmail.com +Message-ID: <20220506091013.1746159-3-ovidiu.panait@windriver.com> + +From: Takashi Iwai + +commit dca947d4d26dbf925a64a6cfb2ddbc035e831a3d upstream. + +In the current PCM design, the read/write syscalls (as well as the +equivalent ioctls) are allowed before the PCM stream is running, that +is, at PCM PREPARED state. Meanwhile, we also allow to re-issue +hw_params and hw_free ioctl calls at the PREPARED state that may +change or free the buffers, too. The problem is that there is no +protection against those mix-ups. + +This patch applies the previously introduced runtime->buffer_mutex to +the read/write operations so that the concurrent hw_params or hw_free +call can no longer interfere during the operation. The mutex is +unlocked before scheduling, so we don't take it too long. + +Cc: +Reviewed-by: Jaroslav Kysela +Link: https://lore.kernel.org/r/20220322170720.3529-3-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Ovidiu Panait +Signed-off-by: Greg Kroah-Hartman +--- + sound/core/pcm_lib.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/sound/core/pcm_lib.c ++++ b/sound/core/pcm_lib.c +@@ -1861,9 +1861,11 @@ static int wait_for_avail(struct snd_pcm + if (avail >= runtime->twake) + break; + snd_pcm_stream_unlock_irq(substream); ++ mutex_unlock(&runtime->buffer_mutex); + + tout = schedule_timeout(wait_time); + ++ mutex_lock(&runtime->buffer_mutex); + snd_pcm_stream_lock_irq(substream); + set_current_state(TASK_INTERRUPTIBLE); + switch (runtime->status->state) { +@@ -2157,6 +2159,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(str + + nonblock = !!(substream->f_flags & O_NONBLOCK); + ++ mutex_lock(&runtime->buffer_mutex); + snd_pcm_stream_lock_irq(substream); + err = pcm_accessible_state(runtime); + if (err < 0) +@@ -2244,6 +2247,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(str + if (xfer > 0 && err >= 0) + snd_pcm_update_state(substream, runtime); + snd_pcm_stream_unlock_irq(substream); ++ mutex_unlock(&runtime->buffer_mutex); + return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; + } + EXPORT_SYMBOL(__snd_pcm_lib_xfer); diff --git a/queue-5.4/series b/queue-5.4/series index 286e9201d6e..d3b8ec5dfa4 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -41,3 +41,9 @@ kvm-lapic-enable-timer-posted-interrupt-only-when-mw.patch net-ipv6-ensure-we-call-ipv6_mc_down-at-most-once.patch block-map-add-__gfp_zero-flag-for-alloc_page-in-function-bio_copy_kern.patch mm-fix-unexpected-zeroed-page-mapping-with-zram-swap.patch +alsa-pcm-fix-races-among-concurrent-hw_params-and-hw_free-calls.patch +alsa-pcm-fix-races-among-concurrent-read-write-and-buffer-changes.patch +alsa-pcm-fix-races-among-concurrent-prepare-and-hw_params-hw_free-calls.patch +alsa-pcm-fix-races-among-concurrent-prealloc-proc-writes.patch +alsa-pcm-fix-potential-ab-ba-lock-with-buffer_mutex-and-mmap_lock.patch +tcp-make-sure-treq-af_specific-is-initialized.patch diff --git a/queue-5.4/tcp-make-sure-treq-af_specific-is-initialized.patch b/queue-5.4/tcp-make-sure-treq-af_specific-is-initialized.patch new file mode 100644 index 00000000000..b6c2492924f --- /dev/null +++ b/queue-5.4/tcp-make-sure-treq-af_specific-is-initialized.patch @@ -0,0 +1,143 @@ +From ba5a4fdd63ae0c575707030db0b634b160baddd7 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Sun, 24 Apr 2022 13:35:09 -0700 +Subject: tcp: make sure treq->af_specific is initialized + +From: Eric Dumazet + +commit ba5a4fdd63ae0c575707030db0b634b160baddd7 upstream. + +syzbot complained about a recent change in TCP stack, +hitting a NULL pointer [1] + +tcp request sockets have an af_specific pointer, which +was used before the blamed change only for SYNACK generation +in non SYNCOOKIE mode. + +tcp requests sockets momentarily created when third packet +coming from client in SYNCOOKIE mode were not using +treq->af_specific. + +Make sure this field is populated, in the same way normal +TCP requests sockets do in tcp_conn_request(). + +[1] +TCP: request_sock_TCPv6: Possible SYN flooding on port 20002. Sending cookies. Check SNMP counters. +general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] PREEMPT SMP KASAN +KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f] +CPU: 1 PID: 3695 Comm: syz-executor864 Not tainted 5.18.0-rc3-syzkaller-00224-g5fd1fe4807f9 #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +RIP: 0010:tcp_create_openreq_child+0xe16/0x16b0 net/ipv4/tcp_minisocks.c:534 +Code: 48 c1 ea 03 80 3c 02 00 0f 85 e5 07 00 00 4c 8b b3 28 01 00 00 48 b8 00 00 00 00 00 fc ff df 49 8d 7e 08 48 89 fa 48 c1 ea 03 <80> 3c 02 00 0f 85 c9 07 00 00 48 8b 3c 24 48 89 de 41 ff 56 08 48 +RSP: 0018:ffffc90000de0588 EFLAGS: 00010202 +RAX: dffffc0000000000 RBX: ffff888076490330 RCX: 0000000000000100 +RDX: 0000000000000001 RSI: ffffffff87d67ff0 RDI: 0000000000000008 +RBP: ffff88806ee1c7f8 R08: 0000000000000000 R09: 0000000000000000 +R10: ffffffff87d67f00 R11: 0000000000000000 R12: ffff88806ee1bfc0 +R13: ffff88801b0e0368 R14: 0000000000000000 R15: 0000000000000000 +FS: 00007f517fe58700(0000) GS:ffff8880b9d00000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00007ffcead76960 CR3: 000000006f97b000 CR4: 00000000003506e0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + + tcp_v6_syn_recv_sock+0x199/0x23b0 net/ipv6/tcp_ipv6.c:1267 + tcp_get_cookie_sock+0xc9/0x850 net/ipv4/syncookies.c:207 + cookie_v6_check+0x15c3/0x2340 net/ipv6/syncookies.c:258 + tcp_v6_cookie_check net/ipv6/tcp_ipv6.c:1131 [inline] + tcp_v6_do_rcv+0x1148/0x13b0 net/ipv6/tcp_ipv6.c:1486 + tcp_v6_rcv+0x3305/0x3840 net/ipv6/tcp_ipv6.c:1725 + ip6_protocol_deliver_rcu+0x2e9/0x1900 net/ipv6/ip6_input.c:422 + ip6_input_finish+0x14c/0x2c0 net/ipv6/ip6_input.c:464 + NF_HOOK include/linux/netfilter.h:307 [inline] + NF_HOOK include/linux/netfilter.h:301 [inline] + ip6_input+0x9c/0xd0 net/ipv6/ip6_input.c:473 + dst_input include/net/dst.h:461 [inline] + ip6_rcv_finish net/ipv6/ip6_input.c:76 [inline] + NF_HOOK include/linux/netfilter.h:307 [inline] + NF_HOOK include/linux/netfilter.h:301 [inline] + ipv6_rcv+0x27f/0x3b0 net/ipv6/ip6_input.c:297 + __netif_receive_skb_one_core+0x114/0x180 net/core/dev.c:5405 + __netif_receive_skb+0x24/0x1b0 net/core/dev.c:5519 + process_backlog+0x3a0/0x7c0 net/core/dev.c:5847 + __napi_poll+0xb3/0x6e0 net/core/dev.c:6413 + napi_poll net/core/dev.c:6480 [inline] + net_rx_action+0x8ec/0xc60 net/core/dev.c:6567 + __do_softirq+0x29b/0x9c2 kernel/softirq.c:558 + invoke_softirq kernel/softirq.c:432 [inline] + __irq_exit_rcu+0x123/0x180 kernel/softirq.c:637 + irq_exit_rcu+0x5/0x20 kernel/softirq.c:649 + sysvec_apic_timer_interrupt+0x93/0xc0 arch/x86/kernel/apic/apic.c:1097 + +Fixes: 5b0b9e4c2c89 ("tcp: md5: incorrect tcp_header_len for incoming connections") +Signed-off-by: Eric Dumazet +Cc: Francesco Ruggeri +Signed-off-by: David S. Miller +[fruggeri: Account for backport conflicts from 35b2c3211609 and 6fc8c827dd4f] +Signed-off-by: Francesco Ruggeri +Signed-off-by: Greg Kroah-Hartman +--- + include/net/tcp.h | 5 +++++ + net/ipv4/syncookies.c | 1 + + net/ipv4/tcp_ipv4.c | 2 +- + net/ipv6/syncookies.c | 1 + + net/ipv6/tcp_ipv6.c | 2 +- + 5 files changed, 9 insertions(+), 2 deletions(-) + +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -2015,6 +2015,11 @@ struct tcp_request_sock_ops { + enum tcp_synack_type synack_type); + }; + ++extern const struct tcp_request_sock_ops tcp_request_sock_ipv4_ops; ++#if IS_ENABLED(CONFIG_IPV6) ++extern const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops; ++#endif ++ + #ifdef CONFIG_SYN_COOKIES + static inline __u32 cookie_init_sequence(const struct tcp_request_sock_ops *ops, + const struct sock *sk, struct sk_buff *skb, +--- a/net/ipv4/syncookies.c ++++ b/net/ipv4/syncookies.c +@@ -332,6 +332,7 @@ struct sock *cookie_v4_check(struct sock + + ireq = inet_rsk(req); + treq = tcp_rsk(req); ++ treq->af_specific = &tcp_request_sock_ipv4_ops; + treq->rcv_isn = ntohl(th->seq) - 1; + treq->snt_isn = cookie; + treq->ts_off = 0; +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -1383,7 +1383,7 @@ struct request_sock_ops tcp_request_sock + .syn_ack_timeout = tcp_syn_ack_timeout, + }; + +-static const struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { ++const struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { + .mss_clamp = TCP_MSS_DEFAULT, + #ifdef CONFIG_TCP_MD5SIG + .req_md5_lookup = tcp_v4_md5_lookup, +--- a/net/ipv6/syncookies.c ++++ b/net/ipv6/syncookies.c +@@ -176,6 +176,7 @@ struct sock *cookie_v6_check(struct sock + + ireq = inet_rsk(req); + treq = tcp_rsk(req); ++ treq->af_specific = &tcp_request_sock_ipv6_ops; + treq->tfo_listener = false; + + if (security_inet_conn_request(sk, skb, req)) +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -800,7 +800,7 @@ struct request_sock_ops tcp6_request_soc + .syn_ack_timeout = tcp_syn_ack_timeout, + }; + +-static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { ++const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { + .mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - + sizeof(struct ipv6hdr), + #ifdef CONFIG_TCP_MD5SIG -- 2.47.3