aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorHarald Welte <laforge@netfilter.org>2005-05-30 18:35:26 -0400
committerDavid S. Miller <davem@davemloft.net>2005-05-30 18:35:26 -0400
commit9bb7bc942d3da606f184ac6a4dfc7e4d470c831b (patch)
treedc310200df5988d4c71c346baad6a923a4bdeb9d /net/ipv4
parent5e485b7975472ba4a408523deb6541e70c451842 (diff)
[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>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/netfilter/ip_queue.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index e5746b674413..eda1fba431a4 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -3,6 +3,7 @@
3 * communicating with userspace via netlink. 3 * communicating with userspace via netlink.
4 * 4 *
5 * (C) 2000-2002 James Morris <jmorris@intercode.com.au> 5 * (C) 2000-2002 James Morris <jmorris@intercode.com.au>
6 * (C) 2003-2005 Netfilter Core Team <coreteam@netfilter.org>
6 * 7 *
7 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 9 * it under the terms of the GNU General Public License version 2 as
@@ -17,6 +18,7 @@
17 * 2005-01-10: Added /proc counter for dropped packets; fixed so 18 * 2005-01-10: Added /proc counter for dropped packets; fixed so
18 * packets aren't delivered to user space if they're going 19 * packets aren't delivered to user space if they're going
19 * to be dropped. 20 * to be dropped.
21 * 2005-05-26: local_bh_{disable,enable} around nf_reinject (Harald Welte)
20 * 22 *
21 */ 23 */
22#include <linux/module.h> 24#include <linux/module.h>
@@ -71,7 +73,15 @@ static DECLARE_MUTEX(ipqnl_sem);
71static void 73static void
72ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict) 74ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict)
73{ 75{
76 /* TCP input path (and probably other bits) assume to be called
77 * from softirq context, not from syscall, like ipq_issue_verdict is
78 * called. TCP input path deadlocks with locks taken from timer
79 * softirq, e.g. We therefore emulate this by local_bh_disable() */
80
81 local_bh_disable();
74 nf_reinject(entry->skb, entry->info, verdict); 82 nf_reinject(entry->skb, entry->info, verdict);
83 local_bh_enable();
84
75 kfree(entry); 85 kfree(entry);
76} 86}
77 87