diff options
author | Harald Welte <laforge@netfilter.org> | 2005-05-30 15:38:14 -0700 |
---|---|---|
committer | Chris Wright <chrisw@osdl.org> | 2005-06-11 19:45:22 -0700 |
commit | 839c2379a6ed8ea9dd669d4c3206b85c5dff674e (patch) | |
tree | fb7cb1c304f0f5f5d14412ee533ca9a2a30d46f3 | |
parent | 43cdfc5ea9a5c7b7904dd040370f6655951412f0 (diff) | |
download | linux-stable-839c2379a6ed8ea9dd669d4c3206b85c5dff674e.tar.gz linux-stable-839c2379a6ed8ea9dd669d4c3206b85c5dff674e.tar.bz2 linux-stable-839c2379a6ed8ea9dd669d4c3206b85c5dff674e.zip |
[PATCH] 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>
Signed-off-by: Chris Wright <chrisw@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | 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 index a9aa12cc83bb..470a9055488e 100644 --- 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@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 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); } |