From: Greg Kroah-Hartman Date: Fri, 3 Aug 2018 05:48:57 +0000 (+0200) Subject: Linux 4.17.12 X-Git-Tag: v4.17.12^0 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c213909194d46430c7d5d38f097a7a9c8be4ffca;p=thirdparty%2Fkernel%2Fstable-queue.git Linux 4.17.12 --- diff --git a/queue-3.18/fasync-fix-deadlock-between-task-context-and-interrupt-context-kill_fasync.patch b/queue-3.18/fasync-fix-deadlock-between-task-context-and-interrupt-context-kill_fasync.patch deleted file mode 100644 index 8242f62f814..00000000000 --- a/queue-3.18/fasync-fix-deadlock-between-task-context-and-interrupt-context-kill_fasync.patch +++ /dev/null @@ -1,118 +0,0 @@ -From foo@baz Sat Jul 28 12:29:48 CEST 2018 -From: Kirill Tkhai -Date: Thu, 5 Apr 2018 14:58:06 +0300 -Subject: fasync: Fix deadlock between task-context and interrupt-context kill_fasync() - -From: Kirill Tkhai - -[ Upstream commit 7a107c0f55a3b4c6f84a4323df5610360bde1684 ] - -I observed the following deadlock between them: - -[task 1] [task 2] [task 3] -kill_fasync() mm_update_next_owner() copy_process() - spin_lock_irqsave(&fa->fa_lock) read_lock(&tasklist_lock) write_lock_irq(&tasklist_lock) - send_sigio() ... - read_lock(&fown->lock) kill_fasync() ... - read_lock(&tasklist_lock) spin_lock_irqsave(&fa->fa_lock) ... - -Task 1 can't acquire read locked tasklist_lock, since there is -already task 3 expressed its wish to take the lock exclusive. -Task 2 holds the read locked lock, but it can't take the spin lock. - -Also, there is possible another deadlock (which I haven't observed): - -[task 1] [task 2] -f_getown() kill_fasync() - read_lock(&f_own->lock) spin_lock_irqsave(&fa->fa_lock,) - send_sigio() write_lock_irq(&f_own->lock) - kill_fasync() read_lock(&fown->lock) - spin_lock_irqsave(&fa->fa_lock,) - -Actually, we do not need exclusive fa->fa_lock in kill_fasync_rcu(), -as it guarantees fa->fa_file->f_owner integrity only. It may seem, -that it used to give a task a small possibility to receive two sequential -signals, if there are two parallel kill_fasync() callers, and task -handles the first signal fastly, but the behaviour won't become -different, since there is exclusive sighand lock in do_send_sig_info(). - -The patch converts fa_lock into rwlock_t, and this fixes two above -deadlocks, as rwlock is allowed to be taken from interrupt handler -by qrwlock design. - -Signed-off-by: Kirill Tkhai -Signed-off-by: Jeff Layton -Signed-off-by: Sasha Levin -Signed-off-by: Greg Kroah-Hartman ---- - fs/fcntl.c | 15 +++++++-------- - include/linux/fs.h | 2 +- - 2 files changed, 8 insertions(+), 9 deletions(-) - ---- a/fs/fcntl.c -+++ b/fs/fcntl.c -@@ -587,9 +587,9 @@ int fasync_remove_entry(struct file *fil - if (fa->fa_file != filp) - continue; - -- spin_lock_irq(&fa->fa_lock); -+ write_lock_irq(&fa->fa_lock); - fa->fa_file = NULL; -- spin_unlock_irq(&fa->fa_lock); -+ write_unlock_irq(&fa->fa_lock); - - *fp = fa->fa_next; - call_rcu(&fa->fa_rcu, fasync_free_rcu); -@@ -634,13 +634,13 @@ struct fasync_struct *fasync_insert_entr - if (fa->fa_file != filp) - continue; - -- spin_lock_irq(&fa->fa_lock); -+ write_lock_irq(&fa->fa_lock); - fa->fa_fd = fd; -- spin_unlock_irq(&fa->fa_lock); -+ write_unlock_irq(&fa->fa_lock); - goto out; - } - -- spin_lock_init(&new->fa_lock); -+ rwlock_init(&new->fa_lock); - new->magic = FASYNC_MAGIC; - new->fa_file = filp; - new->fa_fd = fd; -@@ -703,14 +703,13 @@ static void kill_fasync_rcu(struct fasyn - { - while (fa) { - struct fown_struct *fown; -- unsigned long flags; - - if (fa->magic != FASYNC_MAGIC) { - printk(KERN_ERR "kill_fasync: bad magic number in " - "fasync_struct!\n"); - return; - } -- spin_lock_irqsave(&fa->fa_lock, flags); -+ read_lock(&fa->fa_lock); - if (fa->fa_file) { - fown = &fa->fa_file->f_owner; - /* Don't send SIGURG to processes which have not set a -@@ -719,7 +718,7 @@ static void kill_fasync_rcu(struct fasyn - if (!(sig == SIGURG && fown->signum == 0)) - send_sigio(fown, fa->fa_fd, band); - } -- spin_unlock_irqrestore(&fa->fa_lock, flags); -+ read_unlock(&fa->fa_lock); - fa = rcu_dereference(fa->fa_next); - } - } ---- a/include/linux/fs.h -+++ b/include/linux/fs.h -@@ -1128,7 +1128,7 @@ static inline int lease_modify(struct fi - - - struct fasync_struct { -- spinlock_t fa_lock; -+ rwlock_t fa_lock; - int magic; - int fa_fd; - struct fasync_struct *fa_next; /* singly linked list */ diff --git a/queue-3.18/series b/queue-3.18/series index 59f35a5ef46..2ce370ea9b9 100644 --- a/queue-3.18/series +++ b/queue-3.18/series @@ -52,7 +52,6 @@ scsi-megaraid-silence-a-static-checker-bug.patch bpf-fix-references-to-free_bpf_prog_info-in-comments.patch media-siano-get-rid-of-__le32-__le16-cast-warnings.patch alsa-hda-ca0132-fix-build-failure-when-a-local-macro-is-defined.patch -fasync-fix-deadlock-between-task-context-and-interrupt-context-kill_fasync.patch drm-gma500-fix-psb_intel_lvds_mode_valid-s-return-type.patch ipconfig-correctly-initialise-ic_nameservers.patch rsi-fix-invalid-vdd-warning-in-mmc.patch diff --git a/queue-4.14/fasync-fix-deadlock-between-task-context-and-interrupt-context-kill_fasync.patch b/queue-4.14/fasync-fix-deadlock-between-task-context-and-interrupt-context-kill_fasync.patch deleted file mode 100644 index f306a491f0d..00000000000 --- a/queue-4.14/fasync-fix-deadlock-between-task-context-and-interrupt-context-kill_fasync.patch +++ /dev/null @@ -1,118 +0,0 @@ -From foo@baz Sat Jul 28 10:25:26 CEST 2018 -From: Kirill Tkhai -Date: Thu, 5 Apr 2018 14:58:06 +0300 -Subject: fasync: Fix deadlock between task-context and interrupt-context kill_fasync() - -From: Kirill Tkhai - -[ Upstream commit 7a107c0f55a3b4c6f84a4323df5610360bde1684 ] - -I observed the following deadlock between them: - -[task 1] [task 2] [task 3] -kill_fasync() mm_update_next_owner() copy_process() - spin_lock_irqsave(&fa->fa_lock) read_lock(&tasklist_lock) write_lock_irq(&tasklist_lock) - send_sigio() ... - read_lock(&fown->lock) kill_fasync() ... - read_lock(&tasklist_lock) spin_lock_irqsave(&fa->fa_lock) ... - -Task 1 can't acquire read locked tasklist_lock, since there is -already task 3 expressed its wish to take the lock exclusive. -Task 2 holds the read locked lock, but it can't take the spin lock. - -Also, there is possible another deadlock (which I haven't observed): - -[task 1] [task 2] -f_getown() kill_fasync() - read_lock(&f_own->lock) spin_lock_irqsave(&fa->fa_lock,) - send_sigio() write_lock_irq(&f_own->lock) - kill_fasync() read_lock(&fown->lock) - spin_lock_irqsave(&fa->fa_lock,) - -Actually, we do not need exclusive fa->fa_lock in kill_fasync_rcu(), -as it guarantees fa->fa_file->f_owner integrity only. It may seem, -that it used to give a task a small possibility to receive two sequential -signals, if there are two parallel kill_fasync() callers, and task -handles the first signal fastly, but the behaviour won't become -different, since there is exclusive sighand lock in do_send_sig_info(). - -The patch converts fa_lock into rwlock_t, and this fixes two above -deadlocks, as rwlock is allowed to be taken from interrupt handler -by qrwlock design. - -Signed-off-by: Kirill Tkhai -Signed-off-by: Jeff Layton -Signed-off-by: Sasha Levin -Signed-off-by: Greg Kroah-Hartman ---- - fs/fcntl.c | 15 +++++++-------- - include/linux/fs.h | 2 +- - 2 files changed, 8 insertions(+), 9 deletions(-) - ---- a/fs/fcntl.c -+++ b/fs/fcntl.c -@@ -864,9 +864,9 @@ int fasync_remove_entry(struct file *fil - if (fa->fa_file != filp) - continue; - -- spin_lock_irq(&fa->fa_lock); -+ write_lock_irq(&fa->fa_lock); - fa->fa_file = NULL; -- spin_unlock_irq(&fa->fa_lock); -+ write_unlock_irq(&fa->fa_lock); - - *fp = fa->fa_next; - call_rcu(&fa->fa_rcu, fasync_free_rcu); -@@ -911,13 +911,13 @@ struct fasync_struct *fasync_insert_entr - if (fa->fa_file != filp) - continue; - -- spin_lock_irq(&fa->fa_lock); -+ write_lock_irq(&fa->fa_lock); - fa->fa_fd = fd; -- spin_unlock_irq(&fa->fa_lock); -+ write_unlock_irq(&fa->fa_lock); - goto out; - } - -- spin_lock_init(&new->fa_lock); -+ rwlock_init(&new->fa_lock); - new->magic = FASYNC_MAGIC; - new->fa_file = filp; - new->fa_fd = fd; -@@ -980,14 +980,13 @@ static void kill_fasync_rcu(struct fasyn - { - while (fa) { - struct fown_struct *fown; -- unsigned long flags; - - if (fa->magic != FASYNC_MAGIC) { - printk(KERN_ERR "kill_fasync: bad magic number in " - "fasync_struct!\n"); - return; - } -- spin_lock_irqsave(&fa->fa_lock, flags); -+ read_lock(&fa->fa_lock); - if (fa->fa_file) { - fown = &fa->fa_file->f_owner; - /* Don't send SIGURG to processes which have not set a -@@ -996,7 +995,7 @@ static void kill_fasync_rcu(struct fasyn - if (!(sig == SIGURG && fown->signum == 0)) - send_sigio(fown, fa->fa_fd, band); - } -- spin_unlock_irqrestore(&fa->fa_lock, flags); -+ read_unlock(&fa->fa_lock); - fa = rcu_dereference(fa->fa_next); - } - } ---- a/include/linux/fs.h -+++ b/include/linux/fs.h -@@ -1245,7 +1245,7 @@ static inline int locks_lock_file_wait(s - } - - struct fasync_struct { -- spinlock_t fa_lock; -+ rwlock_t fa_lock; - int magic; - int fa_fd; - struct fasync_struct *fa_next; /* singly linked list */ diff --git a/queue-4.14/series b/queue-4.14/series index bfd0fbf0c32..d4182aa2288 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -176,7 +176,6 @@ dt-bindings-pinctrl-meson-add-support-for-the-meson8m2-soc.patch spi-meson-spicc-fix-error-handling-in-meson_spicc_probe.patch net-hns3-fixes-the-out-of-bounds-access-in-hclge_map_tqp.patch dt-bindings-net-meson-dwmac-new-compatible-name-for-axg-soc.patch -fasync-fix-deadlock-between-task-context-and-interrupt-context-kill_fasync.patch backlight-pwm_bl-don-t-use-gpiof_-with-gpiod_get_direction.patch stop_machine-use-raw-spinlocks.patch delayacct-use-raw_spinlocks.patch diff --git a/queue-4.17/fasync-fix-deadlock-between-task-context-and-interrupt-context-kill_fasync.patch b/queue-4.17/fasync-fix-deadlock-between-task-context-and-interrupt-context-kill_fasync.patch deleted file mode 100644 index dfa531fbb4b..00000000000 --- a/queue-4.17/fasync-fix-deadlock-between-task-context-and-interrupt-context-kill_fasync.patch +++ /dev/null @@ -1,118 +0,0 @@ -From foo@baz Sat Jul 28 10:14:30 CEST 2018 -From: Kirill Tkhai -Date: Thu, 5 Apr 2018 14:58:06 +0300 -Subject: fasync: Fix deadlock between task-context and interrupt-context kill_fasync() - -From: Kirill Tkhai - -[ Upstream commit 7a107c0f55a3b4c6f84a4323df5610360bde1684 ] - -I observed the following deadlock between them: - -[task 1] [task 2] [task 3] -kill_fasync() mm_update_next_owner() copy_process() - spin_lock_irqsave(&fa->fa_lock) read_lock(&tasklist_lock) write_lock_irq(&tasklist_lock) - send_sigio() ... - read_lock(&fown->lock) kill_fasync() ... - read_lock(&tasklist_lock) spin_lock_irqsave(&fa->fa_lock) ... - -Task 1 can't acquire read locked tasklist_lock, since there is -already task 3 expressed its wish to take the lock exclusive. -Task 2 holds the read locked lock, but it can't take the spin lock. - -Also, there is possible another deadlock (which I haven't observed): - -[task 1] [task 2] -f_getown() kill_fasync() - read_lock(&f_own->lock) spin_lock_irqsave(&fa->fa_lock,) - send_sigio() write_lock_irq(&f_own->lock) - kill_fasync() read_lock(&fown->lock) - spin_lock_irqsave(&fa->fa_lock,) - -Actually, we do not need exclusive fa->fa_lock in kill_fasync_rcu(), -as it guarantees fa->fa_file->f_owner integrity only. It may seem, -that it used to give a task a small possibility to receive two sequential -signals, if there are two parallel kill_fasync() callers, and task -handles the first signal fastly, but the behaviour won't become -different, since there is exclusive sighand lock in do_send_sig_info(). - -The patch converts fa_lock into rwlock_t, and this fixes two above -deadlocks, as rwlock is allowed to be taken from interrupt handler -by qrwlock design. - -Signed-off-by: Kirill Tkhai -Signed-off-by: Jeff Layton -Signed-off-by: Sasha Levin -Signed-off-by: Greg Kroah-Hartman ---- - fs/fcntl.c | 15 +++++++-------- - include/linux/fs.h | 2 +- - 2 files changed, 8 insertions(+), 9 deletions(-) - ---- a/fs/fcntl.c -+++ b/fs/fcntl.c -@@ -871,9 +871,9 @@ int fasync_remove_entry(struct file *fil - if (fa->fa_file != filp) - continue; - -- spin_lock_irq(&fa->fa_lock); -+ write_lock_irq(&fa->fa_lock); - fa->fa_file = NULL; -- spin_unlock_irq(&fa->fa_lock); -+ write_unlock_irq(&fa->fa_lock); - - *fp = fa->fa_next; - call_rcu(&fa->fa_rcu, fasync_free_rcu); -@@ -918,13 +918,13 @@ struct fasync_struct *fasync_insert_entr - if (fa->fa_file != filp) - continue; - -- spin_lock_irq(&fa->fa_lock); -+ write_lock_irq(&fa->fa_lock); - fa->fa_fd = fd; -- spin_unlock_irq(&fa->fa_lock); -+ write_unlock_irq(&fa->fa_lock); - goto out; - } - -- spin_lock_init(&new->fa_lock); -+ rwlock_init(&new->fa_lock); - new->magic = FASYNC_MAGIC; - new->fa_file = filp; - new->fa_fd = fd; -@@ -987,14 +987,13 @@ static void kill_fasync_rcu(struct fasyn - { - while (fa) { - struct fown_struct *fown; -- unsigned long flags; - - if (fa->magic != FASYNC_MAGIC) { - printk(KERN_ERR "kill_fasync: bad magic number in " - "fasync_struct!\n"); - return; - } -- spin_lock_irqsave(&fa->fa_lock, flags); -+ read_lock(&fa->fa_lock); - if (fa->fa_file) { - fown = &fa->fa_file->f_owner; - /* Don't send SIGURG to processes which have not set a -@@ -1003,7 +1002,7 @@ static void kill_fasync_rcu(struct fasyn - if (!(sig == SIGURG && fown->signum == 0)) - send_sigio(fown, fa->fa_fd, band); - } -- spin_unlock_irqrestore(&fa->fa_lock, flags); -+ read_unlock(&fa->fa_lock); - fa = rcu_dereference(fa->fa_next); - } - } ---- a/include/linux/fs.h -+++ b/include/linux/fs.h -@@ -1250,7 +1250,7 @@ static inline int locks_lock_file_wait(s - } - - struct fasync_struct { -- spinlock_t fa_lock; -+ rwlock_t fa_lock; - int magic; - int fa_fd; - struct fasync_struct *fa_next; /* singly linked list */ diff --git a/queue-4.17/series b/queue-4.17/series index 5a0794486c2..4ddfe03a160 100644 --- a/queue-4.17/series +++ b/queue-4.17/series @@ -238,7 +238,6 @@ dt-bindings-pinctrl-meson-add-support-for-the-meson8m2-soc.patch spi-meson-spicc-fix-error-handling-in-meson_spicc_probe.patch net-hns3-fixes-the-out-of-bounds-access-in-hclge_map_tqp.patch dt-bindings-net-meson-dwmac-new-compatible-name-for-axg-soc.patch -fasync-fix-deadlock-between-task-context-and-interrupt-context-kill_fasync.patch i40e-add-advertising-10g-lr-mode.patch i40e-avoid-overflow-in-i40e_ptp_adjfreq.patch mt76-add-rcu-locking-around-tx-scheduling.patch diff --git a/queue-4.4/fasync-fix-deadlock-between-task-context-and-interrupt-context-kill_fasync.patch b/queue-4.4/fasync-fix-deadlock-between-task-context-and-interrupt-context-kill_fasync.patch deleted file mode 100644 index e56b747b92d..00000000000 --- a/queue-4.4/fasync-fix-deadlock-between-task-context-and-interrupt-context-kill_fasync.patch +++ /dev/null @@ -1,118 +0,0 @@ -From foo@baz Sat Jul 28 12:10:33 CEST 2018 -From: Kirill Tkhai -Date: Thu, 5 Apr 2018 14:58:06 +0300 -Subject: fasync: Fix deadlock between task-context and interrupt-context kill_fasync() - -From: Kirill Tkhai - -[ Upstream commit 7a107c0f55a3b4c6f84a4323df5610360bde1684 ] - -I observed the following deadlock between them: - -[task 1] [task 2] [task 3] -kill_fasync() mm_update_next_owner() copy_process() - spin_lock_irqsave(&fa->fa_lock) read_lock(&tasklist_lock) write_lock_irq(&tasklist_lock) - send_sigio() ... - read_lock(&fown->lock) kill_fasync() ... - read_lock(&tasklist_lock) spin_lock_irqsave(&fa->fa_lock) ... - -Task 1 can't acquire read locked tasklist_lock, since there is -already task 3 expressed its wish to take the lock exclusive. -Task 2 holds the read locked lock, but it can't take the spin lock. - -Also, there is possible another deadlock (which I haven't observed): - -[task 1] [task 2] -f_getown() kill_fasync() - read_lock(&f_own->lock) spin_lock_irqsave(&fa->fa_lock,) - send_sigio() write_lock_irq(&f_own->lock) - kill_fasync() read_lock(&fown->lock) - spin_lock_irqsave(&fa->fa_lock,) - -Actually, we do not need exclusive fa->fa_lock in kill_fasync_rcu(), -as it guarantees fa->fa_file->f_owner integrity only. It may seem, -that it used to give a task a small possibility to receive two sequential -signals, if there are two parallel kill_fasync() callers, and task -handles the first signal fastly, but the behaviour won't become -different, since there is exclusive sighand lock in do_send_sig_info(). - -The patch converts fa_lock into rwlock_t, and this fixes two above -deadlocks, as rwlock is allowed to be taken from interrupt handler -by qrwlock design. - -Signed-off-by: Kirill Tkhai -Signed-off-by: Jeff Layton -Signed-off-by: Sasha Levin -Signed-off-by: Greg Kroah-Hartman ---- - fs/fcntl.c | 15 +++++++-------- - include/linux/fs.h | 2 +- - 2 files changed, 8 insertions(+), 9 deletions(-) - ---- a/fs/fcntl.c -+++ b/fs/fcntl.c -@@ -587,9 +587,9 @@ int fasync_remove_entry(struct file *fil - if (fa->fa_file != filp) - continue; - -- spin_lock_irq(&fa->fa_lock); -+ write_lock_irq(&fa->fa_lock); - fa->fa_file = NULL; -- spin_unlock_irq(&fa->fa_lock); -+ write_unlock_irq(&fa->fa_lock); - - *fp = fa->fa_next; - call_rcu(&fa->fa_rcu, fasync_free_rcu); -@@ -634,13 +634,13 @@ struct fasync_struct *fasync_insert_entr - if (fa->fa_file != filp) - continue; - -- spin_lock_irq(&fa->fa_lock); -+ write_lock_irq(&fa->fa_lock); - fa->fa_fd = fd; -- spin_unlock_irq(&fa->fa_lock); -+ write_unlock_irq(&fa->fa_lock); - goto out; - } - -- spin_lock_init(&new->fa_lock); -+ rwlock_init(&new->fa_lock); - new->magic = FASYNC_MAGIC; - new->fa_file = filp; - new->fa_fd = fd; -@@ -703,14 +703,13 @@ static void kill_fasync_rcu(struct fasyn - { - while (fa) { - struct fown_struct *fown; -- unsigned long flags; - - if (fa->magic != FASYNC_MAGIC) { - printk(KERN_ERR "kill_fasync: bad magic number in " - "fasync_struct!\n"); - return; - } -- spin_lock_irqsave(&fa->fa_lock, flags); -+ read_lock(&fa->fa_lock); - if (fa->fa_file) { - fown = &fa->fa_file->f_owner; - /* Don't send SIGURG to processes which have not set a -@@ -719,7 +718,7 @@ static void kill_fasync_rcu(struct fasyn - if (!(sig == SIGURG && fown->signum == 0)) - send_sigio(fown, fa->fa_fd, band); - } -- spin_unlock_irqrestore(&fa->fa_lock, flags); -+ read_unlock(&fa->fa_lock); - fa = rcu_dereference(fa->fa_next); - } - } ---- a/include/linux/fs.h -+++ b/include/linux/fs.h -@@ -1254,7 +1254,7 @@ static inline int locks_lock_file_wait(s - } - - struct fasync_struct { -- spinlock_t fa_lock; -+ rwlock_t fa_lock; - int magic; - int fa_fd; - struct fasync_struct *fa_next; /* singly linked list */ diff --git a/queue-4.4/series b/queue-4.4/series index c875a97e174..b12970406ba 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -78,7 +78,6 @@ bpf-fix-references-to-free_bpf_prog_info-in-comments.patch media-siano-get-rid-of-__le32-__le16-cast-warnings.patch drm-atomic-handling-the-case-when-setting-old-crtc-for-plane.patch alsa-hda-ca0132-fix-build-failure-when-a-local-macro-is-defined.patch -fasync-fix-deadlock-between-task-context-and-interrupt-context-kill_fasync.patch memory-tegra-do-not-handle-spurious-interrupts.patch memory-tegra-apply-interrupts-mask-per-soc.patch drm-gma500-fix-psb_intel_lvds_mode_valid-s-return-type.patch diff --git a/queue-4.9/fasync-fix-deadlock-between-task-context-and-interrupt-context-kill_fasync.patch b/queue-4.9/fasync-fix-deadlock-between-task-context-and-interrupt-context-kill_fasync.patch deleted file mode 100644 index 4d05625fb11..00000000000 --- a/queue-4.9/fasync-fix-deadlock-between-task-context-and-interrupt-context-kill_fasync.patch +++ /dev/null @@ -1,118 +0,0 @@ -From foo@baz Sat Jul 28 10:48:22 CEST 2018 -From: Kirill Tkhai -Date: Thu, 5 Apr 2018 14:58:06 +0300 -Subject: fasync: Fix deadlock between task-context and interrupt-context kill_fasync() - -From: Kirill Tkhai - -[ Upstream commit 7a107c0f55a3b4c6f84a4323df5610360bde1684 ] - -I observed the following deadlock between them: - -[task 1] [task 2] [task 3] -kill_fasync() mm_update_next_owner() copy_process() - spin_lock_irqsave(&fa->fa_lock) read_lock(&tasklist_lock) write_lock_irq(&tasklist_lock) - send_sigio() ... - read_lock(&fown->lock) kill_fasync() ... - read_lock(&tasklist_lock) spin_lock_irqsave(&fa->fa_lock) ... - -Task 1 can't acquire read locked tasklist_lock, since there is -already task 3 expressed its wish to take the lock exclusive. -Task 2 holds the read locked lock, but it can't take the spin lock. - -Also, there is possible another deadlock (which I haven't observed): - -[task 1] [task 2] -f_getown() kill_fasync() - read_lock(&f_own->lock) spin_lock_irqsave(&fa->fa_lock,) - send_sigio() write_lock_irq(&f_own->lock) - kill_fasync() read_lock(&fown->lock) - spin_lock_irqsave(&fa->fa_lock,) - -Actually, we do not need exclusive fa->fa_lock in kill_fasync_rcu(), -as it guarantees fa->fa_file->f_owner integrity only. It may seem, -that it used to give a task a small possibility to receive two sequential -signals, if there are two parallel kill_fasync() callers, and task -handles the first signal fastly, but the behaviour won't become -different, since there is exclusive sighand lock in do_send_sig_info(). - -The patch converts fa_lock into rwlock_t, and this fixes two above -deadlocks, as rwlock is allowed to be taken from interrupt handler -by qrwlock design. - -Signed-off-by: Kirill Tkhai -Signed-off-by: Jeff Layton -Signed-off-by: Sasha Levin -Signed-off-by: Greg Kroah-Hartman ---- - fs/fcntl.c | 15 +++++++-------- - include/linux/fs.h | 2 +- - 2 files changed, 8 insertions(+), 9 deletions(-) - ---- a/fs/fcntl.c -+++ b/fs/fcntl.c -@@ -588,9 +588,9 @@ int fasync_remove_entry(struct file *fil - if (fa->fa_file != filp) - continue; - -- spin_lock_irq(&fa->fa_lock); -+ write_lock_irq(&fa->fa_lock); - fa->fa_file = NULL; -- spin_unlock_irq(&fa->fa_lock); -+ write_unlock_irq(&fa->fa_lock); - - *fp = fa->fa_next; - call_rcu(&fa->fa_rcu, fasync_free_rcu); -@@ -635,13 +635,13 @@ struct fasync_struct *fasync_insert_entr - if (fa->fa_file != filp) - continue; - -- spin_lock_irq(&fa->fa_lock); -+ write_lock_irq(&fa->fa_lock); - fa->fa_fd = fd; -- spin_unlock_irq(&fa->fa_lock); -+ write_unlock_irq(&fa->fa_lock); - goto out; - } - -- spin_lock_init(&new->fa_lock); -+ rwlock_init(&new->fa_lock); - new->magic = FASYNC_MAGIC; - new->fa_file = filp; - new->fa_fd = fd; -@@ -704,14 +704,13 @@ static void kill_fasync_rcu(struct fasyn - { - while (fa) { - struct fown_struct *fown; -- unsigned long flags; - - if (fa->magic != FASYNC_MAGIC) { - printk(KERN_ERR "kill_fasync: bad magic number in " - "fasync_struct!\n"); - return; - } -- spin_lock_irqsave(&fa->fa_lock, flags); -+ read_lock(&fa->fa_lock); - if (fa->fa_file) { - fown = &fa->fa_file->f_owner; - /* Don't send SIGURG to processes which have not set a -@@ -720,7 +719,7 @@ static void kill_fasync_rcu(struct fasyn - if (!(sig == SIGURG && fown->signum == 0)) - send_sigio(fown, fa->fa_fd, band); - } -- spin_unlock_irqrestore(&fa->fa_lock, flags); -+ read_unlock(&fa->fa_lock); - fa = rcu_dereference(fa->fa_next); - } - } ---- a/include/linux/fs.h -+++ b/include/linux/fs.h -@@ -1277,7 +1277,7 @@ static inline int locks_lock_file_wait(s - } - - struct fasync_struct { -- spinlock_t fa_lock; -+ rwlock_t fa_lock; - int magic; - int fa_fd; - struct fasync_struct *fa_next; /* singly linked list */ diff --git a/queue-4.9/series b/queue-4.9/series index c7d57a00741..46521834e74 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -112,7 +112,6 @@ mmc-dw_mmc-update-actual-clock-for-mmc-debugfs.patch mmc-pwrseq-use-kmalloc_array-instead-of-stack-vla.patch dt-bindings-pinctrl-meson-add-support-for-the-meson8m2-soc.patch dt-bindings-net-meson-dwmac-new-compatible-name-for-axg-soc.patch -fasync-fix-deadlock-between-task-context-and-interrupt-context-kill_fasync.patch stop_machine-use-raw-spinlocks.patch memory-tegra-do-not-handle-spurious-interrupts.patch memory-tegra-apply-interrupts-mask-per-soc.patch