lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Mon, 10 Feb 2014 16:13:56 +0800
From:	Chuansheng Liu <chuansheng.liu@...el.com>
To:	tglx@...utronix.de
Cc:	linux-kernel@...r.kernel.org,
	Chuansheng Liu <chuansheng.liu@...el.com>,
	xiaoming wang <xiaoming.wang@...el.com>
Subject: [PATCH 1/2] genirq: Fix the possible synchronize_irq() wait-forever

There is below race between irq handler and irq thread:
irq handler                             irq thread

irq_wake_thread()                       irq_thread()
  set bit RUNTHREAD
  ...                                    clear bit RUNTHREAD
                                         thread_fn()
                                         [A]test_and_decrease
                                               thread_active
  [B]increase thread_active

If action A is before action B, after that the thread_active
will be always > 0, and for synchronize_irq() calling, which
will be waiting there forever.

Here put the increasing thread-active before setting bit
RUNTHREAD, which can resolve such race.

Signed-off-by: xiaoming wang <xiaoming.wang@...el.com>
Signed-off-by: Chuansheng Liu <chuansheng.liu@...el.com>
---
 kernel/irq/handle.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 131ca17..5f9fbb7 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -65,7 +65,7 @@ static void irq_wake_thread(struct irq_desc *desc, struct irqaction *action)
 	 * Wake up the handler thread for this action. If the
 	 * RUNTHREAD bit is already set, nothing to do.
 	 */
-	if (test_and_set_bit(IRQTF_RUNTHREAD, &action->thread_flags))
+	if (test_bit(IRQTF_RUNTHREAD, &action->thread_flags))
 		return;
 
 	/*
@@ -126,6 +126,25 @@ static void irq_wake_thread(struct irq_desc *desc, struct irqaction *action)
 	 */
 	atomic_inc(&desc->threads_active);
 
+	/*
+	 * set the RUNTHREAD bit after increasing the threads_active,
+	 * it can avoid the below race:
+	 * irq handler                  irq thread in case it is in
+	 *                                            running state
+	 *
+	 *  set RUNTHREAD bit
+	 *                              clear the RUNTHREAD bit
+	 *...                           thread_fn()
+	 *
+	 *                              due to threads_active==0,
+	 *                              no waking up wait_for_threads
+	 *
+	 * threads_active ++
+	 * After that, the threads_active will be always > 0, which
+	 * will block the synchronize_irq().
+	 */
+	set_bit(IRQTF_RUNTHREAD, &action->thread_flags);
+
 	wake_up_process(action->thread);
 }
 
-- 
1.9.rc0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ