[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#330956: Deadlock in ip_queue when used from LOCAL_IN



Package: kernel-tree-2.6.8
Version: 2.6.8-16

I wasn't sure which package to file this under so I opted for the
kernel-tree package.

Details and patch are available on the netfilter list. This is a
pretty nasty bug.

https://lists.netfilter.org/pipermail/netfilter-devel/2005-July/020513.html

As far as I can tell this is still affecting the 2.6.8 images provided
in sarge, specifically I am using Debian 3.1 (sarge) with all security
updates applied and kernel 2.6.8-2-686-smp .

Text from that link:
--QUOTED TEXT--
Patrick McHardy kaber at trash.net
Thu Jul 21 09:44:44 CEST 2005
Previous message: ip_queue freeze with 2.6.9 RHEL4
Next message: [PATCH] reduce netfilte sk_buff enlargement
Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Eric Leblond wrote:
> I've got one rule only :
>       iptables -A INPUT -p tcp --dport 22 --syn -j ACCEPT
>
> It freezes just after I send the NF_ACCEPT decision.

This looks like a problem we've already fixed in current kernels. Please
try this patch.

-------------- next part --------------
[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 at netfilter.org>
Signed-off-by: David S. Miller <davem at davemloft.net>

---
commit 9bb7bc942d3da606f184ac6a4dfc7e4d470c831b
tree dc310200df5988d4c71c346baad6a923a4bdeb9d
parent 5e485b7975472ba4a408523deb6541e70c451842
author Harald Welte <laforge at netfilter.org> Mon, 30 May 2005 15:35:26 -0700
committer David S. Miller <davem at davemloft.net> Mon, 30 May 2005
15:35:26 -0700

 net/ipv4/netfilter/ip_queue.c |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -3,6 +3,7 @@
  * communicating with userspace via netlink.
  *
  * (C) 2000-2002 James Morris <jmorris at intercode.com.au>
+ * (C) 2003-2005 Netfilter Core Team <coreteam at 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
@@ -17,6 +18,7 @@
  * 2005-01-10: Added /proc counter for dropped packets; fixed so
  *             packets aren't delivered to user space if they're going
  *             to be dropped.
+ * 2005-05-26: local_bh_{disable,enable} around nf_reinject (Harald Welte)
  *
  */
 #include <linux/module.h>
@@ -71,7 +73,15 @@ static DECLARE_MUTEX(ipqnl_sem);
 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);
 }

--END QUOTED TEXT--



Reply to: