--- /dev/null
+From stable-bounces@linux.kernel.org Mon May 30 15:38:33 2005
+Date: Mon, 30 May 2005 15:38:14 -0700 (PDT)
+Message-Id: <20050530.153814.112623060.davem@davemloft.net>
+To: stable@kernel.org
+From: "David S. Miller" <davem@davemloft.net>
+Cc:
+Subject: [PATCH] Netfilter deadlock bug fix
+
+Please add this netfilter deadlock fix from Harald
+Welte to the 2.6.x stable patch queue.
+
+Thanks a lot.
+
+[NETFILTER]: Fix deadlock with ip_queue and tcp local input path.
+
+When we have ip_queue being used from LOCAL_IN, then we end up with a
+situation where the verdicts coming back from userspace traverse the TCP
+input path from syscall context. While this seems to work most of the
+time, there's an ugly deadlock:
+
+syscall context is interrupted by the timer interrupt. When the timer
+interrupt leaves, the timer softirq get's scheduled and calls
+tcp_delack_timer() and alike. They themselves do bh_lock_sock(sk),
+which is already held from somewhere else -> boom.
+
+I've now tested the suggested solution by Patrick McHardy and Herbert Xu to
+simply use local_bh_{en,dis}able().
+
+Signed-off-by: Harald Welte <laforge@netfilter.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+
+--- 1/net/ipv4/netfilter/ip_queue.c 2005-05-27 09:44:32.000000000 +0200
++++ 2/net/ipv4/netfilter/ip_queue.c 2005-05-27 09:47:13.000000000 +0200
+@@ -3,6 +3,7 @@
+ * communicating with userspace via netlink.
+ *
+ * (C) 2000-2002 James Morris <jmorris@intercode.com.au>
++ * (C) 2003-2005 Netfilter Core Team <coreteam@netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+@@ -14,6 +15,7 @@
+ * Zander).
+ * 2000-08-01: Added Nick Williams' MAC support.
+ * 2002-06-25: Code cleanup.
++ * 2005-05-26: local_bh_{disable,enable} around nf_reinject (Harald Welte)
+ *
+ */
+ #include <linux/module.h>
+@@ -66,7 +68,15 @@
+ static void
+ ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict)
+ {
++ /* TCP input path (and probably other bits) assume to be called
++ * from softirq context, not from syscall, like ipq_issue_verdict is
++ * called. TCP input path deadlocks with locks taken from timer
++ * softirq, e.g. We therefore emulate this by local_bh_disable() */
++
++ local_bh_disable();
+ nf_reinject(entry->skb, entry->info, verdict);
++ local_bh_enable();
++
+ kfree(entry);
+ }
+