From: Greg Kroah-Hartman Date: Wed, 24 Nov 2021 18:30:25 +0000 (+0100) Subject: 5.4-stable patches X-Git-Tag: v5.15.5~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=24e0e703afcd42439c2f44cbfadac71b3186fd01;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: alsa-hda-hdac_ext_stream-fix-potential-locking-issues.patch alsa-hda-hdac_stream-fix-potential-locking-issue-in-snd_hdac_stream_assign.patch --- diff --git a/queue-5.4/alsa-hda-hdac_ext_stream-fix-potential-locking-issues.patch b/queue-5.4/alsa-hda-hdac_ext_stream-fix-potential-locking-issues.patch new file mode 100644 index 00000000000..175fb4e49a4 --- /dev/null +++ b/queue-5.4/alsa-hda-hdac_ext_stream-fix-potential-locking-issues.patch @@ -0,0 +1,164 @@ +From 868ddfcef31ff93ea8961b2e81ea7fe12f6f144b Mon Sep 17 00:00:00 2001 +From: Pierre-Louis Bossart +Date: Fri, 24 Sep 2021 14:24:16 -0500 +Subject: ALSA: hda: hdac_ext_stream: fix potential locking issues + +From: Pierre-Louis Bossart + +commit 868ddfcef31ff93ea8961b2e81ea7fe12f6f144b upstream. + +The code for hdac_ext_stream seems inherited from hdac_stream, and +similar locking issues are present: the use of the bus->reg_lock +spinlock is inconsistent, with only writes to specific fields being +protected. + +Apply similar fix as in hdac_stream by protecting all accesses to +'link_locked' and 'decoupled' fields, with a new helper +snd_hdac_ext_stream_decouple_locked() added to simplify code +changes. + +Signed-off-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20210924192417.169243-4-pierre-louis.bossart@linux.intel.com +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + include/sound/hdaudio_ext.h | 2 + + sound/hda/ext/hdac_ext_stream.c | 46 ++++++++++++++++++++++++---------------- + 2 files changed, 30 insertions(+), 18 deletions(-) + +--- a/include/sound/hdaudio_ext.h ++++ b/include/sound/hdaudio_ext.h +@@ -88,6 +88,8 @@ struct hdac_ext_stream *snd_hdac_ext_str + struct snd_pcm_substream *substream, + int type); + void snd_hdac_ext_stream_release(struct hdac_ext_stream *azx_dev, int type); ++void snd_hdac_ext_stream_decouple_locked(struct hdac_bus *bus, ++ struct hdac_ext_stream *azx_dev, bool decouple); + void snd_hdac_ext_stream_decouple(struct hdac_bus *bus, + struct hdac_ext_stream *azx_dev, bool decouple); + void snd_hdac_ext_stop_streams(struct hdac_bus *bus); +--- a/sound/hda/ext/hdac_ext_stream.c ++++ b/sound/hda/ext/hdac_ext_stream.c +@@ -106,20 +106,14 @@ void snd_hdac_stream_free_all(struct hda + } + EXPORT_SYMBOL_GPL(snd_hdac_stream_free_all); + +-/** +- * snd_hdac_ext_stream_decouple - decouple the hdac stream +- * @bus: HD-audio core bus +- * @stream: HD-audio ext core stream object to initialize +- * @decouple: flag to decouple +- */ +-void snd_hdac_ext_stream_decouple(struct hdac_bus *bus, +- struct hdac_ext_stream *stream, bool decouple) ++void snd_hdac_ext_stream_decouple_locked(struct hdac_bus *bus, ++ struct hdac_ext_stream *stream, ++ bool decouple) + { + struct hdac_stream *hstream = &stream->hstream; + u32 val; + int mask = AZX_PPCTL_PROCEN(hstream->index); + +- spin_lock_irq(&bus->reg_lock); + val = readw(bus->ppcap + AZX_REG_PP_PPCTL) & mask; + + if (decouple && !val) +@@ -128,6 +122,20 @@ void snd_hdac_ext_stream_decouple(struct + snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, mask, 0); + + stream->decoupled = decouple; ++} ++EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_decouple_locked); ++ ++/** ++ * snd_hdac_ext_stream_decouple - decouple the hdac stream ++ * @bus: HD-audio core bus ++ * @stream: HD-audio ext core stream object to initialize ++ * @decouple: flag to decouple ++ */ ++void snd_hdac_ext_stream_decouple(struct hdac_bus *bus, ++ struct hdac_ext_stream *stream, bool decouple) ++{ ++ spin_lock_irq(&bus->reg_lock); ++ snd_hdac_ext_stream_decouple_locked(bus, stream, decouple); + spin_unlock_irq(&bus->reg_lock); + } + EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_decouple); +@@ -252,6 +260,7 @@ hdac_ext_link_stream_assign(struct hdac_ + return NULL; + } + ++ spin_lock_irq(&bus->reg_lock); + list_for_each_entry(stream, &bus->stream_list, list) { + struct hdac_ext_stream *hstream = container_of(stream, + struct hdac_ext_stream, +@@ -266,17 +275,16 @@ hdac_ext_link_stream_assign(struct hdac_ + } + + if (!hstream->link_locked) { +- snd_hdac_ext_stream_decouple(bus, hstream, true); ++ snd_hdac_ext_stream_decouple_locked(bus, hstream, true); + res = hstream; + break; + } + } + if (res) { +- spin_lock_irq(&bus->reg_lock); + res->link_locked = 1; + res->link_substream = substream; +- spin_unlock_irq(&bus->reg_lock); + } ++ spin_unlock_irq(&bus->reg_lock); + return res; + } + +@@ -292,6 +300,7 @@ hdac_ext_host_stream_assign(struct hdac_ + return NULL; + } + ++ spin_lock_irq(&bus->reg_lock); + list_for_each_entry(stream, &bus->stream_list, list) { + struct hdac_ext_stream *hstream = container_of(stream, + struct hdac_ext_stream, +@@ -301,18 +310,17 @@ hdac_ext_host_stream_assign(struct hdac_ + + if (!stream->opened) { + if (!hstream->decoupled) +- snd_hdac_ext_stream_decouple(bus, hstream, true); ++ snd_hdac_ext_stream_decouple_locked(bus, hstream, true); + res = hstream; + break; + } + } + if (res) { +- spin_lock_irq(&bus->reg_lock); + res->hstream.opened = 1; + res->hstream.running = 0; + res->hstream.substream = substream; +- spin_unlock_irq(&bus->reg_lock); + } ++ spin_unlock_irq(&bus->reg_lock); + + return res; + } +@@ -378,15 +386,17 @@ void snd_hdac_ext_stream_release(struct + break; + + case HDAC_EXT_STREAM_TYPE_HOST: ++ spin_lock_irq(&bus->reg_lock); + if (stream->decoupled && !stream->link_locked) +- snd_hdac_ext_stream_decouple(bus, stream, false); ++ snd_hdac_ext_stream_decouple_locked(bus, stream, false); ++ spin_unlock_irq(&bus->reg_lock); + snd_hdac_stream_release(&stream->hstream); + break; + + case HDAC_EXT_STREAM_TYPE_LINK: +- if (stream->decoupled && !stream->hstream.opened) +- snd_hdac_ext_stream_decouple(bus, stream, false); + spin_lock_irq(&bus->reg_lock); ++ if (stream->decoupled && !stream->hstream.opened) ++ snd_hdac_ext_stream_decouple_locked(bus, stream, false); + stream->link_locked = 0; + stream->link_substream = NULL; + spin_unlock_irq(&bus->reg_lock); diff --git a/queue-5.4/alsa-hda-hdac_stream-fix-potential-locking-issue-in-snd_hdac_stream_assign.patch b/queue-5.4/alsa-hda-hdac_stream-fix-potential-locking-issue-in-snd_hdac_stream_assign.patch new file mode 100644 index 00000000000..75cd0ad008f --- /dev/null +++ b/queue-5.4/alsa-hda-hdac_stream-fix-potential-locking-issue-in-snd_hdac_stream_assign.patch @@ -0,0 +1,50 @@ +From 1465d06a6d8580e73ae65f8590392df58c5ed2fd Mon Sep 17 00:00:00 2001 +From: Pierre-Louis Bossart +Date: Fri, 24 Sep 2021 14:24:14 -0500 +Subject: ALSA: hda: hdac_stream: fix potential locking issue in snd_hdac_stream_assign() + +From: Pierre-Louis Bossart + +commit 1465d06a6d8580e73ae65f8590392df58c5ed2fd upstream. + +The fields 'opened', 'running', 'assigned_key' are all protected by a +spinlock, but the spinlock is not taken when looking for a +stream. This can result in a possible race between assign() and +release(). + +Fix by taking the spinlock before walking through the bus stream list. + +Signed-off-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20210924192417.169243-2-pierre-louis.bossart@linux.intel.com +Signed-off-by: Takashi Iwai +Cc: Scott Bruce +Signed-off-by: Greg Kroah-Hartman +--- + sound/hda/hdac_stream.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/sound/hda/hdac_stream.c ++++ b/sound/hda/hdac_stream.c +@@ -289,6 +289,7 @@ struct hdac_stream *snd_hdac_stream_assi + int key = (substream->pcm->device << 16) | (substream->number << 2) | + (substream->stream + 1); + ++ spin_lock_irq(&bus->reg_lock); + list_for_each_entry(azx_dev, &bus->stream_list, list) { + if (azx_dev->direction != substream->stream) + continue; +@@ -302,13 +303,12 @@ struct hdac_stream *snd_hdac_stream_assi + res = azx_dev; + } + if (res) { +- spin_lock_irq(&bus->reg_lock); + res->opened = 1; + res->running = 0; + res->assigned_key = key; + res->substream = substream; +- spin_unlock_irq(&bus->reg_lock); + } ++ spin_unlock_irq(&bus->reg_lock); + return res; + } + EXPORT_SYMBOL_GPL(snd_hdac_stream_assign); diff --git a/queue-5.4/series b/queue-5.4/series index 53bc5997a91..f79825ef748 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -96,3 +96,5 @@ usb-max-3421-use-driver-data-instead-of-maintaining-a-list-of-bound-devices.patc ice-delete-always-true-check-of-pf-pointer.patch tlb-mmu_gather-add-tlb_flush_-_range-apis.patch hugetlbfs-flush-tlbs-correctly-after-huge_pmd_unshare.patch +alsa-hda-hdac_ext_stream-fix-potential-locking-issues.patch +alsa-hda-hdac_stream-fix-potential-locking-issue-in-snd_hdac_stream_assign.patch