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 for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Sun, 12 Feb 2017 14:31:23 +0000
From:   Chris Wilson <chris@...is-wilson.co.uk>
To:     linux-kernel@...r.kernel.org
Cc:     intel-gfx@...ts.freedesktop.org,
        Chris Wilson <chris@...is-wilson.co.uk>,
        Tvrtko Ursulin <tvrtko.ursulin@...el.com>,
        Thomas Gleixner <tglx@...utronix.de>,
        Hannes Reinecke <hare@...e.com>, Jens Axboe <axboe@...nel.dk>,
        Bjorn Helgaas <bhelgaas@...gle.com>,
        Alexander Potapenko <glider@...gle.com>,
        Chen Fan <chen.fan.fnst@...fujitsu.com>,
        Ingo Molnar <mingo@...nel.org>,
        "Peter Zijlstra (Intel)" <peterz@...radead.org>,
        Sebastian Andrzej Siewior <bigeasy@...utronix.de>,
        Johannes Thumshirn <jthumshirn@...e.de>,
        Emese Revfy <re.emese@...il.com>,
        Sagi Grimberg <sagi@...mberg.me>,
        Eric Dumazet <edumazet@...gle.com>,
        Tom Herbert <therbert@...gle.com>,
        Ben Hutchings <bhutchings@...arflare.com>
Subject: [PATCH v2] softirq: Prevent looping on disabled tasklets

Disabling a tasklet causes it not to run during tasklet_action, but is
put back onto the runnable tasklet list, and a new softirq raised. As
the softirq is raised from within __do_softirq() this causing
__do_softirq() to loop constantly until its timeslice expires and is
transferred to the ksoftirq thread. ksoftirq then permanently spins,
as on each action, the disabled tasklet keeps reraising the softirq.

Break this vicious cycle by moving the softirq from the action to the
final tasklet_enable().

This behaviour appears to be historic (since the first git import).
However, the looping until timeslice duration (to a max of 2ms) was
first introduced in commit c10d73671ad3 ("softirq: reduce latencies"),
with the restart limit restored in commit 34376a50fb1f ("Fix lockup
related to stop_machine being stuck in __do_softirq.")

v2: Export tasklet_enable() to work with modules.

Reported-by: Tvrtko Ursulin <tvrtko.ursulin@...el.com>
Signed-off-by: Chris Wilson <chris@...is-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@...el.com>
Cc: Thomas Gleixner <tglx@...utronix.de>
Cc: Hannes Reinecke <hare@...e.com>
Cc: Jens Axboe <axboe@...nel.dk>
Cc: Bjorn Helgaas <bhelgaas@...gle.com>
Cc: Alexander Potapenko <glider@...gle.com>
Cc: Chen Fan <chen.fan.fnst@...fujitsu.com>
Cc: Ingo Molnar <mingo@...nel.org>
Cc: "Peter Zijlstra (Intel)" <peterz@...radead.org>
Cc: Sebastian Andrzej Siewior <bigeasy@...utronix.de>
Cc: Johannes Thumshirn <jthumshirn@...e.de>
Cc: Emese Revfy <re.emese@...il.com>
Cc: Sagi Grimberg <sagi@...mberg.me>
Cc: Eric Dumazet <edumazet@...gle.com>
Cc: Tom Herbert <therbert@...gle.com>
Cc: Ben Hutchings <bhutchings@...arflare.com>
---
 include/linux/interrupt.h |  7 +------
 kernel/softirq.c          | 12 ++++++++++--
 2 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 53144e78a369..a1fa88e7e509 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -611,12 +611,7 @@ static inline void tasklet_disable(struct tasklet_struct *t)
 	smp_mb();
 }
 
-static inline void tasklet_enable(struct tasklet_struct *t)
-{
-	smp_mb__before_atomic();
-	atomic_dec(&t->count);
-}
-
+extern void tasklet_enable(struct tasklet_struct *t);
 extern void tasklet_kill(struct tasklet_struct *t);
 extern void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu);
 extern void tasklet_init(struct tasklet_struct *t,
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 080eb57789c4..ab8d9aeccb46 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -535,7 +535,6 @@ static __latent_entropy void tasklet_action(struct softirq_action *a)
 		t->next = NULL;
 		*__this_cpu_read(tasklet_vec.tail) = t;
 		__this_cpu_write(tasklet_vec.tail, &(t->next));
-		__raise_softirq_irqoff(TASKLET_SOFTIRQ);
 		local_irq_enable();
 	}
 }
@@ -571,7 +570,6 @@ static __latent_entropy void tasklet_hi_action(struct softirq_action *a)
 		t->next = NULL;
 		*__this_cpu_read(tasklet_hi_vec.tail) = t;
 		__this_cpu_write(tasklet_hi_vec.tail, &(t->next));
-		__raise_softirq_irqoff(HI_SOFTIRQ);
 		local_irq_enable();
 	}
 }
@@ -587,6 +585,16 @@ void tasklet_init(struct tasklet_struct *t,
 }
 EXPORT_SYMBOL(tasklet_init);
 
+void tasklet_enable(struct tasklet_struct *t)
+{
+	if (!atomic_dec_and_test(&t->count))
+		return;
+
+	if (test_bit(TASKLET_STATE_SCHED, &t->state))
+		raise_softirq(HI_SOFTIRQ | TASKLET_SOFTIRQ);
+}
+EXPORT_SYMBOL(tasklet_enable);
+
 void tasklet_kill(struct tasklet_struct *t)
 {
 	if (in_interrupt())
-- 
2.11.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ