From: Greg Kroah-Hartman Date: Fri, 24 Nov 2023 12:21:17 +0000 (+0000) Subject: 4.14-stable patches X-Git-Tag: v4.14.331~70 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=13781ef7b1d90f43e78dd2a9f5cd304d14bb0f5b;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: alsa-info-fix-potential-deadlock-at-disconnection.patch --- diff --git a/queue-4.14/alsa-info-fix-potential-deadlock-at-disconnection.patch b/queue-4.14/alsa-info-fix-potential-deadlock-at-disconnection.patch new file mode 100644 index 00000000000..1e855ddf826 --- /dev/null +++ b/queue-4.14/alsa-info-fix-potential-deadlock-at-disconnection.patch @@ -0,0 +1,121 @@ +From c7a60651953359f98dbf24b43e1bf561e1573ed4 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 9 Nov 2023 15:19:54 +0100 +Subject: ALSA: info: Fix potential deadlock at disconnection + +From: Takashi Iwai + +commit c7a60651953359f98dbf24b43e1bf561e1573ed4 upstream. + +As reported recently, ALSA core info helper may cause a deadlock at +the forced device disconnection during the procfs operation. + +The proc_remove() (that is called from the snd_card_disconnect() +helper) has a synchronization of the pending procfs accesses via +wait_for_completion(). Meanwhile, ALSA procfs helper takes the global +mutex_lock(&info_mutex) at both the proc_open callback and +snd_card_info_disconnect() helper. Since the proc_open can't finish +due to the mutex lock, wait_for_completion() never returns, either, +hence it deadlocks. + + TASK#1 TASK#2 + proc_reg_open() + takes use_pde() + snd_info_text_entry_open() + snd_card_disconnect() + snd_info_card_disconnect() + takes mutex_lock(&info_mutex) + proc_remove() + wait_for_completion(unused_pde) + ... waiting task#1 closes + mutex_lock(&info_mutex) + => DEADLOCK + +This patch is a workaround for avoiding the deadlock scenario above. + +The basic strategy is to move proc_remove() call outside the mutex +lock. proc_remove() can work gracefully without extra locking, and it +can delete the tree recursively alone. So, we call proc_remove() at +snd_info_card_disconnection() at first, then delete the rest resources +recursively within the info_mutex lock. + +After the change, the function snd_info_disconnect() doesn't do +disconnection by itself any longer, but it merely clears the procfs +pointer. So rename the function to snd_info_clear_entries() for +avoiding confusion. + +The similar change is applied to snd_info_free_entry(), too. Since +the proc_remove() is called only conditionally with the non-NULL +entry->p, it's skipped after the snd_info_clear_entries() call. + +Reported-by: Shinhyung Kang +Closes: https://lore.kernel.org/r/664457955.21699345385931.JavaMail.epsvc@epcpadp4 +Reviewed-by: Jaroslav Kysela +Cc: +Link: https://lore.kernel.org/r/20231109141954.4283-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/core/info.c | 21 +++++++++++++-------- + 1 file changed, 13 insertions(+), 8 deletions(-) + +--- a/sound/core/info.c ++++ b/sound/core/info.c +@@ -72,7 +72,7 @@ struct snd_info_private_data { + }; + + static int snd_info_version_init(void); +-static void snd_info_disconnect(struct snd_info_entry *entry); ++static void snd_info_clear_entries(struct snd_info_entry *entry); + + /* + +@@ -598,11 +598,16 @@ void snd_info_card_disconnect(struct snd + { + if (!card) + return; +- mutex_lock(&info_mutex); ++ + proc_remove(card->proc_root_link); +- card->proc_root_link = NULL; + if (card->proc_root) +- snd_info_disconnect(card->proc_root); ++ proc_remove(card->proc_root->p); ++ ++ mutex_lock(&info_mutex); ++ if (card->proc_root) ++ snd_info_clear_entries(card->proc_root); ++ card->proc_root_link = NULL; ++ card->proc_root = NULL; + mutex_unlock(&info_mutex); + } + +@@ -776,15 +781,14 @@ struct snd_info_entry *snd_info_create_c + } + EXPORT_SYMBOL(snd_info_create_card_entry); + +-static void snd_info_disconnect(struct snd_info_entry *entry) ++static void snd_info_clear_entries(struct snd_info_entry *entry) + { + struct snd_info_entry *p; + + if (!entry->p) + return; + list_for_each_entry(p, &entry->children, list) +- snd_info_disconnect(p); +- proc_remove(entry->p); ++ snd_info_clear_entries(p); + entry->p = NULL; + } + +@@ -801,8 +805,9 @@ void snd_info_free_entry(struct snd_info + if (!entry) + return; + if (entry->p) { ++ proc_remove(entry->p); + mutex_lock(&info_mutex); +- snd_info_disconnect(entry); ++ snd_info_clear_entries(entry); + mutex_unlock(&info_mutex); + } + diff --git a/queue-4.14/series b/queue-4.14/series index 929420e1161..04996ccb87a 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -44,3 +44,4 @@ s390-cmma-fix-handling-of-swapper_pg_dir-and-invalid_pg_dir.patch parisc-prevent-booting-64-bit-kernels-on-pa1.x-machines.patch parisc-pgtable-do-not-drop-upper-5-address-bits-of-physical-address.patch parisc-power-fix-power-soft-off-when-running-on-qemu.patch +alsa-info-fix-potential-deadlock-at-disconnection.patch